我想定义函数:
accumulate_list' :: Num a => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f
| [] f = 0
| (x:xs) f = f x (accumulate_list xs f)
但它没有编译,抱怨x,xs,x,xs不在范围内。
试图获得相同的结果,我已经定义了这个函数
accumulate_list :: Num a => [a] -> ( a -> a -> a ) -> a
accumulate_list [] f = 0
accumulate_list (x:xs) f = f x $ accumulate_list xs f
它编译得很好,如果参数中传递的功能是sum
,那就像列表(+)
一样。是的,我终于发现我确实想要实现的目标已经作为sum
函数存在于Prelude中。
但是,我不明白为什么带有混合警卫和模式匹配的第一个版本不能编译。有什么问题?
答案 0 :(得分:21)
这是因为警卫基本上是一个布尔表达式。他们必须评估为True
或False
。这样的事情应该是样式:
accumulate_list' :: (Eq a, Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f
| l == [] = 0
| otherwise = undefined -- fill out undefined
值得一提的是,自从Haskell 2010中添加了模式防护装置后,您可以将模式和防护装置混合起来:
accumulate_list' :: (Eq a, Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f
| [] <- l = 0 --pattern for the empty list case
| 10 < 5 = 10 --arbitrary regular guard just because
| (x:xs) <- l = undefined --pattern for the non-empty case
答案 1 :(得分:3)
使用@ Sibi提供的答案,我已经完成了它,以便提供完整的工作代码示例:
accumulate_list' :: (Eq a ,Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f
| l == [] = 0
| otherwise = f x $ accumulate_list xs f
where (x:xs) = l