Haskell экземпляр определения класса типов с конструктором типов - PullRequest
5 голосов
/ 07 марта 2019
data CouldBe a = Is a | Lost deriving (Show, Ord)

instance Eq (CouldBe m) where
  Is x == Is y = x == y 
  Lost == Lost = True 
  _ == _ = False 

выдает ошибку: No instance for (Eq m) arising from a use of ‘==’ Итак:

instance (Eq m) => Eq (CouldBe m) where
  Is x == Is y = x == y 
  Lost == Lost = True 
  _ == _ = False 

Работает нормально (по крайней мере, я начинаю понимать ошибки), но зачем мне это ограничение?Я пытаюсь учиться, поэтому «почему» очень важно для меня.

1 Ответ

7 голосов
/ 07 марта 2019

Ваше первоначальное определение гласило, что CouldBe m был экземпляром Eq для любого типа m, даже того, который не имеет Eq экземпляра.Но если это правда, вы должны найти какой-то способ определения Is x == Is y без использования x == y (поскольку вам не нужно m, чтобы иметь экземпляр Eq, x == y не обязательно определен.)

В качестве конкретного примера, он запрещает вам писать что-то вроде

Is (+3) == Is (* 5)  -- (+3) == (*5) is undefined

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


«Допустимый», но тривиальный экземпляр без добавления ограничения:

instance Eq (CouldBe m) where
  Is x == Is y = True
  Lost == Lost = True
  _ == _ = False

Два значения CouldBe m равны, если они совместно используют один и тот же конструктор данных, независимо отЗавершенное значение.Не делается никаких попыток использовать x или y, поэтому их типы могут быть неограниченными.

«Действительный» в кавычках, поскольку это определение может нарушать закон замещения, определенный в http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Eq.html. Предположим, у вас есть функция, которая может разделить значение CouldBe:

couldbe :: b -> (a -> b) -> CouldBe a -> b
couldBe x _ Lost = x
couldBe _ f (Is x) = f x

Нарушение происходит потому, что Is 3 == Is 5 будет истиной, но пусть f = couldbe 0 id.Затем f (Is 3) == f (Is 5) оценивается как 3 == 5, что ложно.

Является ли это на самом деле нарушением или нет, зависит от существования функции, подобной couldbe, которая может видеть "внутри" aCouldBe значение.

...