Я определил двоичное дерево:
data Tree = Null | Node Tree Int Tree
и реализовали функцию, которая выдаст сумму значений всех его узлов:
sumOfValues :: Tree -> Int
sumOfValues Null = 0
sumOfValues (Node Null v Null) = v
sumOfValues (Node Null v t2) = v + (sumOfValues t2)
sumOfValues (Node t1 v Null) = v + (sumOfValues t1)
sumOfValues (Node t1 v t2) = v + (sumOfValues t1) + (sumOfValues t2)
Работает как положено. У меня была идея также попытаться реализовать это с помощью охранников:
sumOfValues2 :: Tree -> Int
sumOfValues2 Null = 0
sumOfValues2 (Node t1 v t2)
| t1 == Null && t2 == Null = v
| t1 == Null = v + (sumOfValues2 t2)
| t2 == Null = v + (sumOfValues2 t1)
| otherwise = v + (sumOfValues2 t1) + (sumOfValues2 t2)
но этот не работает, потому что я не реализовал Eq
, я считаю:
No instance for (Eq Tree)
arising from a use of `==' at zzz3.hs:13:3-12
Possible fix: add an instance declaration for (Eq Tree)
In the first argument of `(&&)', namely `t1 == Null'
In the expression: t1 == Null && t2 == Null
In a stmt of a pattern guard for
the definition of `sumOfValues2':
t1 == Null && t2 == Null
Тогда возникает вопрос: как Haskell может сопоставлять шаблоны, не зная, когда совпадает переданный аргумент, не прибегая к Eq
?
Редактировать
Ваши аргументы, кажется, вращаются вокруг того факта, что Haskell на самом деле не сравнивает аргументы функции, а вместо этого использует "форму" и типы подписи, чтобы узнать, какая подфункция должна соответствовать. Но как насчет этого?
f :: Int -> Int -> Int
f 1 _ = 666
f 2 _ = 777
f _ 1 = 888
f _ _ = 999
При запуске f 2 9
не нужно ли будет использовать Eq
, чтобы узнать, какая из подфункций является правильной? Все они равны (в отличие от моего первоначального примера Tree, когда у нас было Tree / Node / Null). Или это фактическое определение Int
что-то вроде
data Int = -2^32 | -109212 ... | 0 | ... +2^32