Давайте начнем с начала:
data Tree a = Branch a a | Leaf deriving(Show)
Это «дерево» по определению будет содержать ровно два a
значения (в Branch
) или ни одного (Leaf
) . Я не уверен, почему это называется деревом. Похоже, вы не собирались этого делать. Возможно, вы хотели
data Tree a = Branch (Tree a) (Tree a) | Leaf a deriving(Show)
, которое представляет собой дерево со значениями a
в листьях. Или, в качестве альтернативы,
data Tree a = Branch a (Tree a) (Tree a) | Leaf deriving(Show)
, которое представляет собой дерево со значениями a
во внутренних узлах.
В любом случае, давайте рассмотрим вашу проблему:
construct :: (Integral a) => [a] -> Tree a
construct (l:r:xs) = if l>r then Branch l (construct $ r:xs) else ...
Здесь , l
имеет тип a
. Кроме того, construct $ r:xs
дает значение типа Tree a
. Следовательно, они имеют разные типы: a
vs Tree a
.
Затем вы берете эти два значения и передаете их в Branch
, который, по определению, вычисляет два значения одного и того же типа. Компилятор пытается решить равенство типов
a ~ Tree a
, но это сразу же терпит неудачу, поскольку единственным решением будет несуществующий бесконечный тип
a = Tree (Tree (Tree ...))
Наконец, чтобы исправить ваш код, вам нужно будет изменить тип вашего дерева так, чтобы оно действительно было деревом. После этого вам нужно будет адаптировать код construct
к новому типу.
Если я изменю construct (x:[]) = Leaf
на construct (x:[]) = x
, то ошибка возникает в этом x
. Почему?
Поскольку x
имеет тип a
, однако подпись construct
обещает Tree a
, следовательно, требует a ~ Tree a
, как и в предыдущем случае.