Я использую Glasgow Haskell Compiler, Version 7.8.3, stage 2 booted by GHC version 7.6.3
.
Я попытался использовать следующее определение данных для типа List в Haskell:
data Eq a => List a = Nil | Cons a (List a)
Однако флаг -XDatatypeContexts
является обязательным, устаревшим и даже удаленным из языка по умолчанию. Это широко рассматривается как ошибка языка. Я также не хочу использовать специальные флаги для моего определения списка, поскольку я пытаюсь воспроизвести функциональность существующего типа списка. Затем я смог использовать вместо этого следующий сегмент кода:
data List a where
Nil :: List a
Cons :: Eq a => a -> List a -> List a
Он работает нормально. Видимая проблема с этим решением заключается в том, что теперь мне нужно использовать флаг -XGADTs
, от которого я все еще не хочу зависеть в этом случае, поскольку нет необходимости в функционировании встроенной версии списка. Есть ли способ ограничить тип в Cons
значением Eq a
, чтобы я мог сравнивать два списка без флагов компилятора и без использования ключевого слова derived
? Оставшийся код выглядит следующим образом:
instance Eq (List a) where
(Cons a b) == (Cons c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
testfunction = Nil :: List Int
main = print (if testfunction == Nil then "printed" else "not printed")
Я вижу, что работает следующее решение:
data List a = Nil | Cons a (List a)
instance Eq a => Eq (List a) where
(Cons a b) == (Cons c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
testfunction = Nil :: List Int
main = print (if testfunction == Nil then "printed" else "not printed")
Однако по какой-то причине это не работает с ручным определением Eq (здесь Equals).
class Equal a where
(=+=) :: a -> a -> Bool
(/+=) :: a -> a -> Bool
x =+= y = not (x /+= y)
x /+= y = not (x =+= y)
data List a = Nil | Cons a (List a)
instance Equal a => Equal (List a) where
(Cons a b) =+= (Cons c d) = (a =+= c) && (b =+= d)
Nil =+= Nil = True
_ =+= _ = False
testfunction = Nil :: List Int
main = print (if testfunction =+= Nil then "printed" else "not printed")
Я получаю следующую ошибку:
No instance for (Equal Int) arising from a use of ‘=+=’
In the expression: testfunction =+= Nil
In the first argument of ‘print’, namely
‘(if testfunction =+= Nil then "printed" else "not printed")’
In the expression:
print (if testfunction =+= Nil then "printed" else "not printed")
Однако, используя GADT, я могу показать, что мой класс Equal действительно работает. Этот код работает:
class Equal a where
(=+=) :: a -> a -> Bool
(/+=) :: a -> a -> Bool
x =+= y = not (x /+= y)
x /+= y = not (x =+= y)
data List a where
Nil :: List a
Cons :: Equal a => a -> List a -> List a
instance Equal (List a) where
(Cons a b) =+= (Cons c d) = (a =+= c) && (b =+= d)
Nil =+= Nil = True
_ =+= _ = False
testfunction = Nil :: List Int
main = print (if testfunction =+= Nil then "printed" else "not printed")
Однако я должен использовать instance Equal (List a) where
вместо instance Equal a => Equal (List a) where
, иначе я получаю сообщение об ошибке:
No instance for (Equal Int) arising from a use of ‘=+=’
In the expression: testfunction =+= Nil
In the first argument of ‘print’, namely
‘(if testfunction =+= Nil then "printed" else "not printed")’
In the expression:
print (if testfunction =+= Nil then "printed" else "not printed")
Equal Int
, которую вы получаете, связана с тем, что нет экземпляра дляEqual Int
:-P. Вы должны определить его:instance Equal Int where ...
(На самом деле довольно редко правильное решение отсутствия ошибок экземпляра состоит в том, чтобы определить экземпляр, но в этом случае это так) - person luqui   schedule 29.05.2015Cons 1 Nil :: List Int
вместоNil :: List Int
; вы по-прежнему получите сообщение об ошибкеNo instance for (Equal Int)
. Проблема в том, что вы не определили, как вы можете использоватьInt
с=+=
, прежде чем пытаться использоватьList Int
с=+=
; это не имеет ничего общего с тем, используете ли вы подход GADT или подход ограничения экземпляра. Подход GADT не снимает бремени доказательства того, что элементы в списке можно сравнить на предмет равенства, он просто переносит бремя доказывания с сайтов использования==
на строительные площадки ваших списков. - person Ben   schedule 29.05.2015