在Haskell中应用函数列表

6
我写了一个函数,可以将一组函数应用到一个项上。
applyAll :: [a -> b] -> a -> [b]
applyAll [] _ = []
applyAll (f:fs) x = (f x) : (applyAll fs x)

有没有更好的方式来做这件事情?
3个回答

21

实际上,这个函数已经作为单子函数的特殊情况存在:

applyAll :: [a -> b] -> a -> [b]
applyAll = sequence

4
值得指出的是,当您将“f”视为“(a ->)”时,“[f b] -> f [b]”可以与“[a -> b] -> (a -> [b])”相统一。 (不要担心它不是有效语法,它可以很好地传达意思。) - Carl
1
@Carl,我从来没有理解为什么那不是有效的语法。 - dfeuer
李的解决方案可能在某些情况下更有效,但这个函数因为已经是一个库函数而获得了一点分数。 - dfeuer
@dfeuer:我记得在某个地方看到过,一个原因可能是通常的章节规则不适用;例如,在Haskell中(-> b)是无效的。我同意我仍然希望不规则章节语法可用!但至少有一些解释。 - Antal Spector-Zabusky

12

您可以使用:

 applyAll l v = fmap ($ v) l

fmap将一个函数提升到输入列表(实际上是任何Functor)上。$的类型为(a -> b) -> a -> b,因此它将一个函数应用于给定值。($ v)是一个section,它将给定的函数应用于v


5
何时使用这种方式不比使用显式递归更好呢?它更加优雅、更加简洁、更加通用、可能更易于优化,可以任意地内嵌定义。 - leftaroundabout

6

李的解决方案是我会推荐的,但这种说法甚至更好:

import Control.Applicative

applyAll' fs v = fs <*> pure v

或者

applyAll'' fs v = fs <*> [v]

这使得事情比必要的更加复杂,我们只需要列表的Functor实例,而applyAll'则是从Applicative实例中注入并立即提取。


这个特定的等价关系在几个月前帮助我思考了一些事情。 - dfeuer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接