如何在Haskell中实现f(g x)(h x)点自由?
How to implement f (g x) (h x) point-freely in Haskell?
从this answer学习如何在Haskell中以毫无意义的方式实现函数\x y z -> f x (g y z)
,其中f
和g
是函数。我的问题是
How to write the function \x -> f (g x) (h x)
in a pointfree manner in Haskell? Here f
g
h
are functions for which f (g x) (h x)
is defined.
我目前的想法是这样的。
uncurry f (mapTuple ($ x) (g, h))
但几次尝试表明这是错误的;甚至 map ($ x) [g, h]
部分也很可疑:如果 g
和 h
的范围不同怎么办?
此外,可读性在这里不是太大的问题。
真诚感谢任何帮助。
如 melpomene 所建议,\x -> f (g x) (h x)
等同于 liftM2 f g h
。
当您对如何将 Haskell 代码转换为 pointfree Haskell 代码有疑问时,您可以尝试 Pointfree.io.
这是一个很好的工具,它经常可以告诉你什么时候不要使用 pointfree 代码,因为它有时会变得完全不可读:-)
arrow 版本为
uncurry f . (g &&& h)
或
(g &&& h) >>> uncurry f
如图:
g ────
╱ ╲
──── &&& >>> uncurry f ───
╲ ╱
h ────
应用式
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
本帖仅用于收集整理评论中的答案。
根据@PetrPudlák评论中link中的抽象-消除过程,我们也可以写成
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
如果翻译成Applicative风格,我们得到:
f <$> g <*> h
那么这个系统化的方法就可以应用到所有的lambda项上,给出point-free风格。 :)
从this answer学习如何在Haskell中以毫无意义的方式实现函数\x y z -> f x (g y z)
,其中f
和g
是函数。我的问题是
How to write the function
\x -> f (g x) (h x)
in a pointfree manner in Haskell? Heref
g
h
are functions for whichf (g x) (h x)
is defined.
我目前的想法是这样的。
uncurry f (mapTuple ($ x) (g, h))
但几次尝试表明这是错误的;甚至 map ($ x) [g, h]
部分也很可疑:如果 g
和 h
的范围不同怎么办?
此外,可读性在这里不是太大的问题。
真诚感谢任何帮助。
如 melpomene 所建议,\x -> f (g x) (h x)
等同于 liftM2 f g h
。
当您对如何将 Haskell 代码转换为 pointfree Haskell 代码有疑问时,您可以尝试 Pointfree.io.
这是一个很好的工具,它经常可以告诉你什么时候不要使用 pointfree 代码,因为它有时会变得完全不可读:-)
arrow 版本为
uncurry f . (g &&& h)
或
(g &&& h) >>> uncurry f
如图:
g ────
╱ ╲
──── &&& >>> uncurry f ───
╲ ╱
h ────
应用式
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
本帖仅用于收集整理评论中的答案。 根据@PetrPudlák评论中link中的抽象-消除过程,我们也可以写成
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
如果翻译成Applicative风格,我们得到:
f <$> g <*> h
那么这个系统化的方法就可以应用到所有的lambda项上,给出point-free风格。 :)