在练习2 here中,我向编译器提供了这个解决方案并得到了无限类型错误。
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: flatten left :: flatten right
这与我第一次练习的解决方案似乎没有什么不同:
sum : Tree Int -> Int
sum tree =
case tree of
Empty -> 0
Node v left right ->
v + sum left + sum right
我想知道这个问题是否与操作顺序有关,所以我添加了parens以确保在flatten
之前评估::
,但这似乎没有什么区别:
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: (flatten left) :: (flatten right)
所以现在我只是难倒了。
答案 0 :(得分:4)
::
是cons
operator,这意味着它会将单个元素添加到列表中。它的类型签名是a -> List a -> List a
。这意味着这不是有效代码,因为第一个参数[v]
是一个列表:
[v] :: flatten left :: flatten right -- invalid!
如果要连接两个列表,请使用连接运算符:++
。您可以在示例中将::
替换为++
以使其编译:
[v] ++ flatten left ++ flatten right
表示该行的另一种方法是连接两个列表,然后使用v
运算符在cons
前面添加列表。
v :: flatten left ++ flatten right
-- The following is the same as above, but with parentheses showing precedence
v :: (flatten left ++ flatten right)
当然,有更有效的方法可以做到这一点,但它突出了cons
和连接之间的区别。
您的sum
示例的工作原因是因为它返回的是int而不是int的列表。您在sum
中返回的类型与树中的值相同,因此您最终得到的是聚合,而不是另一个列表。