Подтвердить что ты не робот

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

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

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

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 является единственно возможной группой с двумя элементами из-за ограничений). Есть ли способ сделать эту работу?

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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, но это не гарантирует, что компилятор их будет использовать. Общим примером являются монадические законы