Нет экземпляра для (Eq a), возникающего в результате использования '==' - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь написать экземпляр Eq для этого типа данных:

data Tree a b = Leaf b | Node a (Tree a b) (Tree a b)
deriving (Show)

Я написал тривиальный код, который, я думал, будет работать:

instance Eq (Tree a b) where
  (Leaf x) == (Leaf y) =  x == y
  (Node val1 l1 r1) == (Node val2 l2 r2)  =  (val1 == val2) && (l1==l2) && (r1==r2)
  _  == _  = False

Но тогда я получаю ошибку:

• No instance for (Eq a) arising from a use of ‘==’
  Possible fix: add (Eq a) to the context of the instance declaration
• In the first argument of ‘(&&)’, namely ‘(val1 == val2)’
  In the expression: (val1 == val2) && (l1 == l2) && (r1 == r2)
  In an equation for ‘==’:
     (Node val1 l1 r1) == (Node val2 l2 r2)
     = (val1 == val2) && (l1 == l2) && (r1 == r2)

Я пытался добавить Eq a => ..., но затем я получаю ту же ошибку для типа b. И я не могу добавить Eq b.

Любая помощь будет оценена, 10x!

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Вы пишете экземпляр, где вызываете функцию (==) в случаях a и b:

instance Eq (Tree a b) where
  (Leaf <b>x</b>) == (Leaf <b>y</b>) = <b>x == y</b>
  (Node <b>val1</b> l1 r1) == (Node <b>val2</b> l2 r2) = (<b>val1 == val2</b>) && (l1==l2) && (r1==r2)
  _  == _  = False

Но x и y в первом предложении являются экземплярами a, а val1 и val2 во втором предложении - экземплярами b. Это не сказал, что вы можете сравнить их. Например, вы не можете проверить равенство двух функций (в информатике принципиально невозможно проверить, равны ли две функции вообще). В результате в этом случае мы никогда не сможем определить, равны ли два дерева.

В любом случае, Haskell замечает, что вы используете функцию (==) :: Eq c => c -> c -> Bool с операндами x и y (в первом предложении), и, следовательно, Eq a, необходимо. То же самое относится и ко второму предложению: мы видим, что вы вызываете (==) с двумя b экземплярами, поэтому Eq b требуется. Нам нужно добавить эти ограничения типа в объявление instance:

instance <b>(Eq a, Eq b) =></b> Eq (Tree a b) where
  (Leaf x) == (Leaf y) = x == y
  (Node val1 l1 r1) == (Node val2 l2 r2) = (val1 == val2) && (l1==l2) && (r1==r2)
  _  == _  = False

Как следствие, вы можете проверить равенство только двух деревьев, поскольку a и b дерева - это типы, которые являются экземпляром класса типов Eq. Но это логично, поскольку, если вы, например, не можете сравнивать значения Leaf s, то как вы можете сказать, равно ли дерево или нет?

0 голосов
/ 12 мая 2018

Как вы уже написали, вы должны поставить ограничения типа Eq a и Eq b.Вы просто должны поместить ограничения в скобки и разделить их запятой.

instance (Eq a, Eq b) => Eq (Tree a b) where
  (Leaf x) == (Leaf y) =  x == y
  (Node val1 l1 r1) == (Node val2 l2 r2)  =  (val1 == val2) && (l1==l2) && (r1==r2)
  _  == _  = False
...