Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Is there any way to do this?

like image 756
user3023182 Avatar asked Nov 22 '13 20:11

user3023182


2 Answers

This is, using so-called applicative style,

h <$> f <*> g

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


An alternative is to lift h into the (->) r applicative functor with

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 somethings, and then feeds an r to get the somethings out of the functions.


The liftA* and the corresponding combination of <$> and <*> are equivalent.

like image 126
kqr Avatar answered Oct 05 '22 21:10

kqr


While @kqr has the more practical solution based on the Applicative instance for ((->) a), we can also talk about it in the "pipey" method

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

which provides a very compositional kind of pointfree program. We'll create this program with tools from Control.Arrow.

First we get the rightmost part of our diagram using a common missing function in Haskell called diag or dup

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

then the middle is created using the (***) combinator from 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   :: (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.

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 ----+
like image 20
J. Abrahamson Avatar answered Oct 05 '22 21:10

J. Abrahamson