Классы типов в типах данных Haskell

В Haskell можно определить тип данных следующим образом:

data Point1 = Point1 {
    x :: Integer
  , y :: Integer
}

Можно ли использовать классы типов для переменных внутри типа данных? Если да, то как? Я понимаю, что можно сделать это как алгебраический тип данных с различным определением для каждого типа точки, но мне интересно, есть ли способ сделать это более компактным и гибким способом.

например Что-то вроде этого псевдокода, в котором используется синтаксис объявления функции:

data Point2 = Point2 {
    x :: (Num a, Ord a) => a
  , y :: (Num a, Ord a) => a
}

Цель состоит в том, чтобы разрешить хранить значения Int, Integer, Float или Double в типе данных. В идеале я хотел бы ограничить его так, чтобы x и y были одного типа.


person Gregyski    schedule 05.07.2009    source источник


Ответы (2)


Вам нужно решить, хотите ли вы экзистенциальную или универсальную количественную оценку этого типа. Универсальная количественная оценка, аля:

data (Num a, Ord a) => Point2 a = Point2 a a

дает обязательство доказательства того, что экземпляры Num и Ord существуют для типа 'a', но на самом деле не очень помогают, потому что все, что он делает, это дает вам обязательство, когда вы переходите к использованию класса Point, создавая значение этого типа или когда вы переходите к шаблону, сопоставьте его.

Почти во всех случаях вам лучше определить

data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read)

и делая каждый из ваших экземпляров зависимым от дополнительной информации, которую вы хотите.

instance Num a => Num (Point2 a) where
    ...

instance (Num a, Ord a) => SomeClass (Point2 a) where
    ...

Это позволяет передавать и создавать меньше лишних словарей и увеличивает количество сценариев, в которых может использоваться ваш тип данных Point2.

С другой стороны, экзистенциальная количественная оценка может позволить вам сказать, что вам вообще все равно, что это за тип (ближе к тому, что вы на самом деле просили, тип мудрый) за счет того, что вы не можете использовать в нем что-либо, кроме предоставленных операций. по указанным вами ограничениям - здесь довольно плохо.

person Edward KMETT    schedule 06.07.2009
comment
Woohoo, это именно то, что я получил в своем комментарии к ответу newacct, но было слишком ленив, чтобы написать :) - person ephemient; 06.07.2009
comment
Это очень информативно. В конечном итоге я использовал комментарий ephemient выше в своем коде. И ваше объяснение очень помогло моему пониманию. (RWH еще не охватил экземпляр, но из контекста очевидно, что он делает.) Большое спасибо. - person Gregyski; 09.07.2009

что-то вроде этого?

data (Num a, Ord a) => Point2 a = Point2 {
    x :: a
  , y :: a
}
person newacct    schedule 05.07.2009
comment
Чаще всего в объявлении данных не учитывается контекст и используется (Num a, Ord a) = ›Point2 a в местах, где тип фактически используется, но это тоже работает. - person ephemient; 05.07.2009
comment
Спасибо. Это работает отлично и даже имеет смысл сейчас, когда я это вижу. - person Gregyski; 05.07.2009