我有三个函数x y z和一个名为functionComposer的函数。
我希望functionComposer将函数x y z作为参数,并返回一个函数,该函数使用y和z的结果作为x的参数并应用x。
用数学符号表示:x(y(a),z(b))
我不是要求这样做:functionComposer x y z = x.y.z
例如:
double x = x + x
summer x y = x + y
functionComposer summer double double = summer (double) (double)
如果x = 2,结果应为8(2 + 2)+(2 + 2)
答案 0 :(得分:10)
你也可以像(->) a
一样使用适用的实例
import Control.Applicative
funcComp summer double1 double2 = summer <$> double1 <*> double2
或monad实例
funcComp summer double1 double2 = liftM2 summer double1 double2
理解这一点的方法是,对于(->) a
,applicative和monad实例都旨在对double1
和double2
都接受的函数值进行“参数化”。 / p>
答案 1 :(得分:5)
使用您的符号:
functionComposer summer double1 double2 = \x -> summer (double1 x) (double2 x)
\x -> ...
表示将x
映射到...
的函数。
注意我必须为double
函数参数指定不同的名称,因为通常你想要编写不同的函数。
答案 2 :(得分:1)
我不知何故觉得你好像想要一系列令人困惑的点,所以:
functionComposer :: (c -> d -> e) -> (a -> c) -> (b -> d) -> a -> b -> e
functionComposer x y z = (. z) . (x . y)
来自“自然地”来自
functionComposer x y z a = (x . y) a . z
但为什么要停在那里?
functionComposer x y = (. (x . y)) . flip (.)
不,更多:
functionComposer x = (. flip (.)) . flip (.) . (x .)
更多!
functionComposer = (((. flip (.)) . flip (.)) .) . (.)
答案 3 :(得分:0)
您基本上是在并行评估y
和z
“ 1 ”。表达这一点的最基本的组合是(***) :: Arrow f => f a c -> f b d -> f (a, b) (c, d)
。您想要提供给x
的结果,所以基本上您想要写
x . (y***z) -- or x <<< y***z
现在这并不是很有效,因为箭头组合器与元组一起工作。所以你需要取消x
。同样地,如果你想让整个事物以正常的咖喱方式接受论证,那么你必须讨论(a,b)
元组。虽然很容易:
functionComposer :: (c -> d -> e) -> (a -> c) -> (b -> d) -> a -> b -> e
functionComposer x y z = curry $ uncurry x <<< y *** z
1 介意,我不是指多线程意义上的并行,只是“语义上并行”。