Search code examples
haskellpointfree

Pointfree returning a tuple in Haskell


Can a pointfree function return a tuple? For instance, can the following be written in pointfree style (where f1, f2, and f3 have been defined):

(\t -> (f1 t, f2 t, f3 t))

In this case, my f1, f2, and f3 are compositions of quot, mod, *, and some integers.

(\f1,f2,f3 -> (\t -> (f1 t, f2 t, f3 t)))

is a more general case, and is equivalent to

(\f1,f2,f3,t -> (f1 t, f2 t, f3 t))

Named functions are OK, but my examples are anonymous. (Named examples would be as follows)

f x = (f1 x, f2 x, f3 x)
f f1 f2 f3 x = (f1 x, f2 x, f3 x)

EDIT: I'm just curious for fun, I'm not going to do this.


Solution

  • You can write

    (\t -> (f1 t, f2 t, f3 t))
    

    pointfree, it's

    liftM (,,) f1 `ap` f2 `ap` f3
    

    with ap from Control.Monad and the Monad instance of (->) a from Control.Monad.Instances. A somewhat more readable form may be the Control.Applicative variant

    (,,) <$> f1 <*> f2 <*> f3
    

    You can then further point-free

    (\f1 f2 f3 -> (\t -> (f1 t, f2 t, f3 t)))
    

    As

      \f1 f2 f3 -> (,,) <$> f1 <*> f2 <*> f3
    = \f1 f2 -> ((,,) <$> f1 <*> f2 <*>)
    = \f1 f2 -> (<*>) ((,,) <$> f1 <*> f2)
    = \f1 f2 -> ((<*>) . ((,,) <$> f1 <*>)) f2
    = \f1 -> (<*>) . ((,,) <$> f1 <*>)
    = \f1 -> (<*>) . (<*>) ((,,) <$> f1)
    = \f1 -> (((<*>) .) . (<*>) . (<$>) (,,)) f1
    = ((<*>) .) . (<*>) . (<$>) (,,)
    

    but seriously, you shouldn't. Keep it readable, that means a bit of pointfreeing is good, but don't overdo it.