【问题标题】:Creating a Haskell function using foldl to turn a list of ints to a single int使用 foldl 创建 Haskell 函数以将 int 列表转换为单个 int
【发布时间】:2016-10-07 19:41:29
【问题描述】:

我必须定义一个函数 prob2,它接受一个 Int 列表并使用 foldl 返回一个 Int:

HW3*> prob2 [2,3,4,5]

2345

我缺乏使用折叠的经验。我有的是这样的:

prob2 :: [Integer] -> Integer

prob2 (x:xs) = foldl (\x->10*x+xs) 0

【问题讨论】:

  • 或者,prob2 = foldl (+) 0 . map (+ 10)

标签: haskell


【解决方案1】:

问题是您仍在考虑递归。您似乎认为问题在于将函数应用于元素的头部和尾部。
但是foldl 采用二元运算符并以累积方式将其应用于列表的元素。对于相同类型的项目,它需要一个二元运算符。

您需要一个带有 2 个参数的 lambda 表达式,如下所示:

foldl (\x y -> 10*x+y) 0  [2,3,4,5]

这将产生您的整数 2345。

【讨论】:

    【解决方案2】:

    还有一种我喜欢使用的象征性看待这个的方式。为了简单起见,让我们先看看foldl1,而不是foldl。请注意,使用 foldl1 通常不是一个好主意,因为它是一个偏函数(传递空列表会导致异常)。

    您可以想象foldl1 接受一个运算符和一个列表,并用该运算符替换列表中的逗号(当然还有适当放置的括号),例如

    foldl1 (+) [1, 2, 3, 4] =
    (((1 + 2) + 3) + 4)     =
    ((3 + 3) + 4)           =
    (6 + 4)                 =
    10
    

    如果运算符的关联性成立,您自然可以完全省略括号。由此可见,您传递给foldl 的运算符/函数当时总是对两个单个元素进行操作。

    请注意,foldl 函数更通用,因为初始/结果值的类型不必与列表元素的类型相同,但如果您想象初始值,上述可视化仍然适用作为“站在”列表的前面:

    (+>) :: Show a => String -> a -> String
    (+>) accumulator x = accumulator ++ show x
    
    foldl (+>) "" [1, 2, 3, 4]     =
    (((("" +> 1) +> 2) +> 3) +> 4) =
    ((("1" +> 2) +> 3) +> 4)       =
    (("12" +> 3) +> 4)             =
    ("123" +> 4)                   =
    "1234"
    

    【讨论】:

    • +1 表示“用此运算符替换列表中的逗号”。顺便说一句,问题指出最终结果应该是整数,而不是字符串。
    • @S.L.Barth:我知道,但我认为您的回答已经负责回答 OP 的具体问题,所以我的意思是后一个示例作为演示累加器类型和元素的一种方式的列表不必相同。
    • 确实是一个有用的补充。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 2011-02-16
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多