Есть ли способ реализовать ограничения в классах типов Haskell? - PullRequest
11 голосов
/ 12 февраля 2010

Есть ли способ ( любой способ) реализовать ограничения в классах типов?

В качестве примера того, о чем я говорю, предположим, что я хочу реализовать группу как класс типов. Таким образом, тип будет группой, если есть три функции:

class Group a where
    product :: a -> a -> a  
    inverse :: a -> a 
    identity :: a

Но это не какие-то функции, но они должны быть связаны некоторыми ограничениями. Например:

product a identity = a 
product a (inverse a) = identity
inverse identity = identity

и т.д ...

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

 data C2 = E | C 

 instance Group C2 where
      identity = E 
      inverse C = C

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

Ответы [ 3 ]

11 голосов
/ 13 февраля 2010

Есть ли способ применить такое ограничение?

Нет. Многие людей просили об этом, включая прославленного Тони Хоара, но на горизонте еще ничего не появляется.

Эта проблема была бы отличной темой обсуждения для группы Haskell Prime . Если кто-нибудь предложил хорошее предложение, его, вероятно, можно найти там.

P.S. Это важная проблема!

8 голосов
/ 13 февраля 2010

В некоторых случаях вы можете указать свойства, используя QuickCheck. Это не совсем принудительное применение, но оно позволяет вам предоставлять общие тесты, которые должны пройти все экземпляры. Например, с помощью уравнения вы можете сказать:

prop_EqNeq x y = (x == y) == not (x != y)

Конечно, автор экземпляра должен вызвать этот тест.

Было бы интересно сделать это для законов монады.

5 голосов
/ 12 февраля 2010

Классы типов могут содержать как определения, так и объявления. Пример:

class Equality a where
    (?=), (!=) :: a -> a -> Bool

    a ?= b = not (a != b)
    a != b = not (a ?= b)

instance Eq a => Equality a where
    (?=) = (==)

test = (1 != 2)

Вы также можете указать специальные ограничения (назовем их законы ) в простом Haskell, но не гарантируется, что компилятор будет их использовать. Типичным примером являются монадические законы

...