从this answer开始,我们将学习如何在Haskell中以无意义的方式实现函数\x y z -> f x (g y z)
,其中f
和g
是函数。我的问题是
如何在Haskell中以无点的方式编写函数
\x -> f (g x) (h x)
?此处f
g
h
是定义f (g x) (h x)
的函数。
我目前想到的想法如下:
uncurry f (mapTuple ($ x) (g, h))
但是几次尝试表明这是错误的;甚至部分map ($ x) [g, h]
也是可疑的:如果g
和h
有不同的范围会怎么样?
此外,可读性不是一个问题。
真心感谢任何帮助。
答案 0 :(得分:6)
arrow版本将是
uncurry f . (g &&& h)
或
(g &&& h) >>> uncurry f
如图:
g ────
╱ ╲
──── &&& >>> uncurry f ───
╲ ╱
h ────
答案 1 :(得分:3)
根据melpomene建议,\x -> f (g x) (h x)
相当于liftM2 f g h
。
当您对如何将Haskell代码转换为pointfree Haskell代码有疑问时,您可以尝试Pointfree.io。
这是一个很棒的工具,通常可以告诉你何时不使用无点代码,因为它有时完全不可读: - )
答案 2 :(得分:2)
应用型式
f <$> g <*> h
join ((g ~> h ~> id) f)
join (f $* g $$ h *$ id)
lurryA @N1 (f <$> (g <$> _1) <*> (h <$> _1))
lurryA @N4 (_1 <*> (_2 <*> _4) <*> (_3 <*> _4)) f g h
答案 3 :(得分:0)
这仅用于收集和整理评论中的答案。 根据@PetrPudlák评论链接中的抽象 - 消除过程,我们也可以写
S (S (K f) (S (K g) I)) (S (K h) I),
或者,在eta减少之后,
S (S (K f) g) h,
其中
S x y z = x z (y z)
K x y = x
特别是在Haskell中,感谢@melpomene指出这一点,S
的角色由ap
扮演,K
扮演const
角色。因此我们可以写
ap (ap (const f) g) h
事实上我们可以进一步减少:
ap (const f) g = f . g
所以我们的功能可以写成:
ap (f . g) h
如果翻译成适用风格,我们会获得:
f <$> g <*> h
然后,这种系统方法可以应用于所有lambda项,并给出无点样式。 :)