【问题标题】:redefining the 'all' function in haskell [duplicate]重新定义haskell中的'all'函数[重复]
【发布时间】:2020-11-22 10:17:12
【问题描述】:

如何使用foldr 在haskell 中重新定义all 函数? 我试过这样写,但我不确定为什么它不起作用。

all :: (a -> Bool) -> [a] -> Bool
all p (x:xs) = foldr (&&) True ((p x) : (all p xs))

【问题讨论】:

标签: haskell higher-order-functions fold


【解决方案1】:

我认为您误解了foldr 的工作原理。这个想法是,对于列表,foldr 用折叠函数替换 (:)。因此,这意味着 fold 函数的第二个参数已经是折叠列表其余部分的结果。

这意味着对于:

all' :: Foldable f => (a -> Bool) -> f a -> Bool
all' p xs = foldr f True xs
    where f = …

f 有两个参数:列表的一个元素,以及列表rest 上的foldr f True。因此,您可以假设第二个参数已经是列表其余部分调用的 all' 函数。

因此我们可以在元素x 上调用p,然后用列表其余部分的all' 计算逻辑与,所以:

all' :: Foldable f => (a -> Bool) -> f a -> Bool
all' p xs = foldr f True xs
    where f x as = p x && as

所以这里x 是列表的头元素,as 是列表其余部分调用的all'

我们可以将f x as = p x && as重写为f x = (p x &&),甚至可以用f = (&&) . p无点,那么我们可以将all'重写为:

all' :: Foldable f => (a -> Bool) -> f a -> Bool
all' p = foldr ((&&) . p) True

甚至可以通过以下方式使 all' 无积分:

all' :: Foldable f => (a -> Bool) -> f a -> Bool
all' = flip foldr True . ((&&) .)

【讨论】:

    【解决方案2】:

    您正在混合foldr 和用它定义的函数。您用foldr 定义all,而不是allfoldr 捕获递归模式,它替换显式递归。

    你需要的是

    all p xs  =  foldr (&&) True (map p xs)
              =  foldr ((&&) . p) True xs
    

    因为

    all p [       x,             y       ]  = 
    all p (       x :            y :  [] )  =
     =          p x &&        (p y && True )
     = ((&&) . p) x ( ((&&) . p) y    True )
    

    因为这就是foldr g z xs :它将xs 中的: 替换为g,并将[] 替换为z,例如[x, y] = (x : y : []) 变成 x `g` (y `g` z) = g x (g y z)

    我们也使用

    (f . g) x  =  f (g x)
    

    根据定义(. 称为“函数组合运算符”),并且

    (&&) p q  =  p && q
    

    因为在 Haskell 中,将中缀运算符括在括号中可以让我们将 is 视为一个函数。

    【讨论】:

      猜你喜欢
      • 2020-03-01
      • 1970-01-01
      • 2020-07-14
      • 2015-12-28
      • 2012-02-02
      • 2016-06-16
      • 1970-01-01
      • 2011-02-08
      • 2023-03-12
      相关资源
      最近更新 更多