【问题标题】:Pattern-Matching mixed with guards模式匹配与警卫混合
【发布时间】:2014-08-25 20:21:45
【问题描述】:

我想定义函数:

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

但是,我不明白为什么混合防护和模式匹配的第一个版本无法编译。有什么问题?

【问题讨论】:

    标签: haskell pattern-matching


    【解决方案1】:

    这是因为守卫基本上是一个布尔表达式。他们必须评估为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
    

    【讨论】:

      【解决方案2】:

      使用@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 
      

      【讨论】:

      • 你可以写accumul l f = case l of [] -&gt; 0; (x:xs) | 5 &lt; 10 -&gt; ...; ...,它实际上混合了模式匹配和守卫。
      猜你喜欢
      • 1970-01-01
      • 2011-09-28
      • 2019-03-01
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      相关资源
      最近更新 更多