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

use*_*182 8 haskell fork pointfree

我猜想我想要J的叉功能.有没有办法做到这一点?

kqr*_*kqr 15

这是,使用所谓的适用风格,

h <$> f <*> g
Run Code Online (Sandbox Code Playgroud)

使用<$>和<*>来自Control.Applicative.


另一种方法是用一个升级h到(->) rapplicative functor

liftA2 h f g
Run Code Online (Sandbox Code Playgroud)

这背后的直觉是,如果

h        ::    a     ->    b     ->   c
-- then --
liftA2 h :: (r -> a) -> (r -> b) -> r -> c
Run Code Online (Sandbox Code Playgroud)

因此,提升版本需要两个函数r -> something而不是实际的somethings,然后提供一个r以从something函数中获取s.


该liftA*和的相应组合<$>和<*>是相等的.


J. *_*son 12

虽然@kqr具有基于Applicative实例的更实用的解决方案((->) a),但我们也可以在"管道"方法中讨论它

        +----- f ------+
       /                \
<---- h                  +------< x
       \                /
        +----- g ------+
Run Code Online (Sandbox Code Playgroud)

它提供了一种非常有组织的无点程序.我们将使用来自的工具创建此程序Control.Arrow.

首先,我们得在Haskell使用一个共同的缺失功能我们图中最右边的部分称为diag或dup

--+
   \
    +----- x        dup :: x -> (x, x)
   /                dup x = (x, x)
--+
Run Code Online (Sandbox Code Playgroud)

然后使用(***)组合器创建中间Control.Arrow

----- f -----     (***)   :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
                  f       :: (a -> b)
                  g       ::             (c -> d)
----- g -----     f *** g ::                         (a, c) -> (b, d)
Run Code Online (Sandbox Code Playgroud)

然后左侧正是我们uncurry所做的

  +--    uncurry   :: (a -> b -> c) -> (a, b) -> c
 /       h         :: (a -> b -> c)
h        uncurry h ::                  (a, b) -> c
 \   
  +--
Run Code Online (Sandbox Code Playgroud)

然后将它们连接在一起我们可以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 ----+
Run Code Online (Sandbox Code Playgroud)