Haskell - добавить класс типов? - PullRequest
4 голосов
/ 30 июля 2011

Рассмотрим следующий пример:

data Dot = Dot Double Double
data Vector = Vector Double Double

Во-первых, я хотел бы перегрузить оператор + для добавления Vector.Если бы я хотел перегрузить оператор равенства (==), я бы написал его следующим образом:

instance Eq Vector where ...blahblahblah

Но я не могу найти, если есть Add класс типов, чтобы Vector вел себя как типс операцией сложения.Я даже не могу найти полный список классов типов Haskell, я знаю только несколько из разных уроков.Существует ли такой список?

Кроме того, можно ли перегрузить оператор + для добавления Vector к Dot (это кажется довольно логичным, не так ли?).

Ответы [ 4 ]

13 голосов
/ 30 июля 2011

Простой способ узнать, к какому классу типов (если есть) принадлежит функция, - это использовать GHCi:

Prelude> :i (+)
class (Eq a, Show a) => Num a where
  (+) :: a -> a -> a
  ...
        -- Defined in GHC.Num
infixl 6 +
7 голосов
/ 30 июля 2011

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

Невозможно перегрузить только + для вашего типа, если только вы не хотите скрыть оператор Prelude + (что означает, что вам нужно создать свой собственный экземпляр Addable для Integer, Double и т. Д., Если вы все еще хотите иметь возможностьиспользуйте + на числах).

5 голосов
/ 30 июля 2011

Вы можете написать instance Num Vector для перегрузки + для сложения векторов (и других операторов, которые имеют смысл).

instance Num Vector where
    (Vector x1 y1) + (Vector x2 y2) = Vector (x1 + x2) (y1 + y2)
    -- and so on

Однако обратите внимание, что + имеет тип Num a => a -> a -> aт.е. оба операнда и результат должны быть одного типа.Это означает, что вы не можете иметь Dot плюс Vector быть Dot.

Хотя вы можете скрыть Num от Prelude и указать свой собственный +, это скорее всеговызвать путаницу и затруднить использование вашего кода вместе с обычной арифметикой.

Я предлагаю вам определить свой собственный оператор для сложения векторной точки, например,

(Dot x y) `offsetBy` (Vector dx dy) = Dot (x + dx) (y + dy)

или другой вариант с использованием символов, если вы предпочитаете что-то более короткое.

4 голосов
/ 30 июля 2011

Иногда я вижу людей, определяющих своих собственных операторов, которые похожи на операторов из Prelude. Даже ++, вероятно, использует этот символ, потому что они хотели чего-то, что передавало бы идею "сложения" двух списков вместе, но не имело смысла, чтобы списки были экземпляром Num. Таким образом, вы можете использовать <+> или |+| или что-то еще.

...