模式匹配与警卫混合

时间:2014-08-25 20:21:46

标签: haskell pattern-matching

我想定义函数:

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中。

但是,我不明白为什么带有混合警卫和模式匹配的第一个版本不能编译。有什么问题?

2 个答案:

答案 0 :(得分:21)

这是因为警卫基本上是一个布尔表达式。他们必须评估为TrueFalse。这样的事情应该是样式:

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