Типы классов в типах данных 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 должны быть одного типа.

Ответы

Ответ 1

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

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.

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

Ответ 2

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

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