【问题标题】:Foldl on a list of functions in Haskell在 Haskell 中的函数列表上折叠
【发布时间】:2020-03-03 13:02:25
【问题描述】:

我正在尝试编写一个函数 pipe,它采用数学函数列表,pipe [f1,...,fn] x 应该返回 f1(f2(...(fn x))) 我已经这样设置了:

pipe :: [(a -> a)] -> (a -> a)
pipe fs   = foldLeft f base fs
  where
    f a x =    
    base  = 

-- >>> pipe [] 3
-- 3
--
-- >>> pipe [(\x -> x+x), (\x -> x + 3)] 3
-- 12
--
-- >>> pipe [(\x -> x * 4), (\x -> x + x)] 3
-- 24

使用 foldl 解决此问题的最佳方法是什么? 谢谢!

【问题讨论】:

  • 认为foldLeftbase应该是什么?你完全没有直觉吗? PS这个函数叫做foldl,没有foldLeft这样的东西。 (而且我不相信这会像左折叠一样起作用,尽管我必须考虑一下 - 在 Haskell 中使用右折叠通常更自然。)
  • 我对 haskell 很陌生——但想象 foldLeft 与 foldl 相同。只是有点不知道从哪里开始
  • 首先写下fbase 必须具有的类型。 (我在上面评论的第一句话中不小心写了foldLeft,我的意思是f。)这应该使它们应该是相当明显的。
  • 我认为base 应该是fs。我已经在我的帖子中添加了函数的预期结果。 f 应该是一个函数,它以某种方式将上一个术语的函数与中心的“fs”堆叠在一起。我可能离这里很远,我很迷茫。
  • 我了解您希望该功能做什么(我检查过,foldl 确实和foldr 一样好用)。但是base 不能是fs,因为它们有不同的类型。说真的,写下fbase 的类型——这会让事情更清楚。只要确保类型匹配,您会惊讶于 Haskell 能走多远。考虑base 的另一种方式是:如果给定一个空列表,您希望pipe 做什么?

标签: haskell foldleft


【解决方案1】:

使用 foldl 应该是:

pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl (\rs f -> f . rs) id fs 

或带有 eta:

pipe :: [(a -> a)] -> (a -> a)
pipe = foldl (\rs f -> f . rs) id 

与另一个 eta:

pipe :: [(a -> a)] -> (a -> a)
pipe = foldl (.) id 

以你为例:

pipe [(\x -> x * 4), (\x -> x + x)] 3
=> 24 

【讨论】:

    【解决方案2】:

    pipe 实际上可以比你想象的要简单得多,而且没有必要使用效率相当低的foldl(你甚至可以在自己的括号中看到这一点——它们是右结合的):只需flip (foldr id)。到达那里的步骤:

    pipe [f1,...,fn] x
    f1 (f2 (... (fn x)))            -- your definition of pipe
    id f1 (id f2 (... (id fn x)))   -- id x = x
    foldr id x [f1,...,fn]          -- the definition of foldr
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 2018-10-11
      • 1970-01-01
      相关资源
      最近更新 更多