简体   繁体   English

有没有办法在Haskell中使h(fx)(gx)无点?

[英]Is there a way to make h (f x) (g x) point-free in Haskell?

I want something like J's fork feature, I guess. 我猜想我想要J的叉功能。 Is there any way to do this? 有没有办法做到这一点?

This is, using so-called applicative style, 这是,使用所谓的适用风格,

h <$> f <*> g

using <$> and <*> from Control.Applicative . 使用Control.Applicative <$><*>


An alternative is to lift h into the (->) r applicative functor with 另一种方法是将h提升到(->) r applicative functor中

liftA2 h f g

The intuition behind that is that if 这背后的直觉是,如果

h        ::    a     ->    b     ->   c
-- then --
liftA2 h :: (r -> a) -> (r -> b) -> r -> c

so the lifted version takes two functions r -> something instead of the actual something s, and then feeds an r to get the something s out of the functions. 所以提升版本需要两个函数r -> something而不是实际的something ,然后输入一个r来从r中获取something


The liftA* and the corresponding combination of <$> and <*> are equivalent. liftA*<$><*>的相应组合是等效的。

While @kqr has the more practical solution based on the Applicative instance for ((->) a) , we can also talk about it in the "pipey" method 虽然@kqr具有基于((->) a)Applicative实例的更实用的解决方案,但我们也可以在“pipey”方法中讨论它

        +----- f ------+
       /                \
<---- h                  +------< x
       \                /
        +----- g ------+

which provides a very compositional kind of pointfree program. 它提供了一种非常有组织的无点程序。 We'll create this program with tools from Control.Arrow . 我们将使用Control.Arrow工具创建此程序。

First we get the rightmost part of our diagram using a common missing function in Haskell called diag or dup 首先,我们使用Haskell中常见的缺失函数diagdup来获取图表中最右边的部分

--+
   \
    +----- x        dup :: x -> (x, x)
   /                dup x = (x, x)
--+

then the middle is created using the (***) combinator from Control.Arrow 然后使用Control.Arrow(***)组合器创建中间

----- f -----     (***)   :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
                  f       :: (a -> b)
                  g       ::             (c -> d)
----- g -----     f *** g ::                         (a, c) -> (b, d)

then the left side is exactly what uncurry does for us 然后左侧正是uncurry为我们做

  +--    uncurry   :: (a -> b -> c) -> (a, b) -> c
 /       h         :: (a -> b -> c)
h        uncurry h ::                  (a, b) -> c
 \   
  +--

Then wiring them all together we can erase the x points with a very compositional style. 然后将它们连接在一起我们可以用非常合成的样式擦除x点。

m :: (a -> b -> c) -> (x -> a) -> (x -> b) -> x -> c
m h f g = uncurry h . (f *** g) . dup

                  +------ f ----+
                 /               \
         <----- h                 +-----------< x (eta reduced)
                 \               /
                  +------ g ----+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM