如何在Haskell中自由地实现f(g x)(h x)?

时间:2016-07-23 15:51:16

标签: haskell pointfree

this answer开始,我们将学习如何在Haskell中以无意义的方式实现函数\x y z -> f x (g y z),其中fg是函数。我的问题是

  

如何在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]也是可疑的:如果gh有不同的范围会怎么样?

此外,可读性不是一个问题。

真心感谢任何帮助。

4 个答案:

答案 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

这是一个很棒的工具,通常可以告诉你何时不使用无点代码,因为它有时完全不可读: - )

enter image description here

答案 2 :(得分:2)

应用型式

f <$> g <*> h

Control.Compose

join ((g ~> h ~> id) f)

Data.Function.Meld

join (f $* g $$ h *$ id)

Data.Function.Tacit

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项,并给出无点样式。 :)