【问题标题】:Haskell function that applies a list of functions to a list of inputs?将函数列表应用于输入列表的 Haskell 函数?
【发布时间】:2020-03-09 06:23:25
【问题描述】:

我需要一个 Haskell 函数,它接受一个函数列表和一个元素列表,并将函数应用于如下元素:第一个函数应用于第一个元素,第二个函数应用于第二个元素,等等。如果有列表停止,我希望功能停止。 我想出的定义是这样的:

apply :: [(a -> b)] -> [a] -> [b]

我希望它像这样工作:

apply [(+1), (*3), (^2)] [1,2,3] == [2,6,9]
apply [even, odd] [1..] == [False, False]

到目前为止我尝试过的事情:

apply :: [(a -> b)] -> [a] -> [b]
apply [] _ = []
apply (f:fs) x = (f x) : (apply fs x)

【问题讨论】:

  • zipWith 绝对是一个有用的功能。正如上述评论者所说,zipWith ($)zipWith id 都会做你想做的事。它们是相同的,因为 ($) 实际上与 id 相同,只是仅限于功能(起初这有点令人震惊,但这是真的,我鼓励你找出原因) - 因为这个原因我更喜欢使用($),因为更明显的是您在谈论函数应用程序。

标签: haskell functional-programming


【解决方案1】:

正如评论的那样,您的递归在第二个参数中无法递归,因此定义将是

apply (f:fs) (x:xs) = (f x) : (apply fs xs) 
apply _      _      = []

您可以使用

apply = zipWith ($) -- zipWith id works too as @Redu commented

或者更有趣的是,你可以通过ZipList 疯狂应用

import Control.Applicative
apply f x = getZipList $ ZipList f <*> ZipList x

【讨论】:

    【解决方案2】:

    有趣的是,在两个 cmets 中有两个完全有效的答案:

    applyAll' :: [b -> c] -> [b] -> [c]
    applyAll = zipWith ($)
    

    applyAll :: [a -> c] -> [a] -> [c]
    applyAll' = zipWith id
    

    有趣的是,Haskell,由于its way to pick types(类型推断),稍微改变了它的签名,显然它们是等价的。 当 id 仅限于函数时,id$ 函数是等价的。 (正如 Robin 在评论中指出的那样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 1970-01-01
      • 2022-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多