【问题标题】:Using foldr with only two parameters使用只有两个参数的 foldr
【发布时间】:2019-08-04 23:33:40
【问题描述】:

我有一些练习来准备 Haskell/Prolog 中的考试。

Haskell 的一个任务是重写下面的函数:

original :: [Integer] -> Integer
original [] = 0
original (x:xs) | x < 20    = 5 * x - 3 + original xs
                | otherwise = original xs

但条件是我只允许删除下面方案中的两个“未定义”:

alternative :: [Integer] -> Integer
alternative = foldr undefined undefined

我的问题是我不知道这如何匹配具有 3 个参数(函数、“起始值”或如何调用的?、列表)的普通 foldr 结构?

也许一个等效的例子会有所帮助,请不要完整的灵魂!

此外,我不允许使用“let”或“where”。

感谢您的帮助!

Sooo...我只是按照@hugo 的想法首先以“正常”方式完成任务,这有​​效但我们的大学校正工具不允许:

alternative :: [Integer] -> Integer
alternative list = foldr (\ x y -> if x < 20 then 5*x -3 + y else y) 0 list

在尝试结束错误后我得到了解决方案:

alternative :: [Integer] -> Integer
alternative = foldr (\ x y -> if x < 20 then 5*x -3 + y else y) 0

【问题讨论】:

  • 提示:foldr 是列表中的某种变态:您可以将(:) 替换为第一个参数,将[] 替换为第二个参数,然后得到@ 的结果987654328@.
  • 部分应用/柯里化意味着每当你将一个函数应用到一个参数上时,你会得到一个带有剩余参数的函数。 foldr(a -&gt; b -&gt; b) -&gt; b -&gt; [a] -&gt; b 类型,所以如果你给它两个参数(适当的类型)你会得到一个类型为 [a] -&gt; b 的函数,它与你在这里想要得到的匹配。
  • 忽略一些细微之处,alternative = foldr undefined undefined 等价于alternative x = foldr undefined undefined x
  • @rene:你如何开始编写 alternative 函数,忽略你提到的参数约束?将其添加到您的问题中,人们会从那里帮助您(除非您一路弄清楚,这很可能发生!)
  • @rene 是的,你需要了解柯里化和偏应用。关键思想是所有函数,包括foldr,都采用 one 参数。其中一些碰巧返回另一个函数,因此可以接受另一个参数,依此类推。这里foldra-&gt;b-&gt;b 作为参数,并返回b-&gt;[a]-&gt;b。如果将另一个b 类型的参数应用于结果,那么我们会得到另一个[a]-&gt;b 类型的结果,它与alternative 的类型匹配。

标签: haskell fold


【解决方案1】:

[1,4,2,5] 这样的列表是(:) 1 ((:) 4 ((:) 2 ((:) 5 []))) 的语法糖。 foldr f z 基本上将(:) 数据构造函数替换为f,将空列表数据构造函数[] 替换为z。所以foldr f z 将导致f 1 (f 4 (f 2 (f 5 z)))

既然你写了original [] = 0,这就意味着对于z,我们可以使用0。对于f,我们可以使用if x &lt; 20 then (+) (5*x-3) else id,因为在x &lt; 20 的情况下,我们将5*x-3 添加到值中,否则,我们对递归计算的值不做任何事情。

因此,我们可以创建一个如下所示的alternative 实现:

alternative :: (Foldable  f, Num a, Ord a) => f a -> a
alternative = foldr f 0
    where f x ys | x < 20 = 5*x - 3 + ys
                 | otherwise = ys

或者没有带有内联 lambda 表达式的 where 子句:

alternative :: (Foldable  f, Num a, Ord a) => f a -> a
alternative = foldr (\x -> if x < 20 then (+) (5*x-3) else id) 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2015-05-25
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    相关资源
    最近更新 更多