Clojure有一个宏->
,它接受一段数据和一组函数,将数据应用于第一个函数,然后将第一个函数的结果应用于下一个函数,将 that 的结果应用于第三个函数,依此类推,最后返回上一个应用程序的结果。
我很喜欢这样,因为这样就不必按照应用的顺序反序编写函数,如下所示:(伪代码如下)
floor (square.root (x))
您可以按照数据流经它们的顺序来编写它们:
-> x (square.root, floor)
我的问题是,在函数式语言中,这个函数是否有一个标准的名称,就像map、reduce和filter有标准的名称一样?Clojure文档将其描述为“通过函数线程化数据”,但我在谷歌上搜索单词thread
却找不到任何相关信息。我在Haskell中写了一个简单的版本:
thread :: a -> [(a -> a)] -> a
thread x [] = x
thread x (f:fs) = thread (f x) fs
在Hoogle上搜索a -> [(a -> a)] -> a
,但也没有任何结果。
在研究这个问题的时候,我还发现,你可以使用Haskell中Control.Arrow
的函数组合运算符来做一件非常类似的事情,如下所示:
($2) (sin >>> cos >>> tan)
而使用专用的高阶thread
函数,则可以编写:
thread 2 [sin, cos, tan]
第一个公式是否足以实际应用?
7条答案
按热度按时间qyzbxkaa1#
您要查找的名称是function composition。
线程宏和
comp
之间的区别在于前者利用了Clojure的同象性,而后者更接近于合成的数学定义。事实上,如果您在每个步骤中创建一个具有一个参数的函数,并颠倒函数的顺序,则可以将线程宏调用转换为
comp
调用:qf9go6mv2#
我想你可以使用
foldl
来完成这个任务,并使用适当的参数:参数如下:
(\x y -> y x)
是一个接受函数y
并将其应用于自变量x
的函数。y
将被列表中的每个函数替代。2
是要给予函数的初始参数。[f1, f2, f3]
是函数列表。foldl
使用这些参数计算以下内容:f3(f2(f1(2)))
.px9o7tmv3#
假设
>>>
类似于bash shell的管道操作符rooted from Unix,我将把它称为 pipeline sequence combinator。vnjpjtjt4#
这并不是您要寻找的函数,但该函数有一个“惯用名称”:
一个有经验的Haskeller甚至不需要去想这意味着什么;它是一个词就足够了。
如果每个函数都获取 previous 而不是 next 的输出,则您所要求的函数将为
但如果你能管理它,就使用前一个版本(其一,它更懒;即,给定函数的无限列表,它可以产生结果)。
nx7onnlm5#
你不能在haskell中有这样的函数,因为它只限于接受和返回相同类型的函数,这不是很有用。
但您可以使用其中一种
功能组成:
或箭头:
i1icjdpr6#
奥利弗Steele在他的函数式Javascript库中称之为
sequence
。pipe
可能也是一个不错的名字。xu3bshqb7#
和Haskell一样,OCaml的限制是所有涉及的函数都需要接受和返回相同的类型。
h (g (f x))
也可以用|>
运算符表示为x |> f |> g |> h
,所以如果我们以x
作为初始值,将运算符折叠到函数列表上,我们就完成了目标。我们也可以使用
Fun.flip
来实现函数列表的部分应用。如果涉及的类型是多态的,请注意值限制。