foxterfox
foxterfox

Reputation: 75

Compose functions into another function

Is there a function for Haskell in the standard library which takes three functions and returns a function which applies the return values of the first two functions to the third function, something like this:

compact :: (a -> b) -> (a -> c) -> (b -> c -> d) -> a -> d
compact a b c = \x -> c (a x) (b x)

Or this:

import Control.Arrow
compact' :: (a -> b) -> (a -> c) -> (b -> c -> d) -> a -> d
compact' a b c = uncurry c . (a &&& b)

So that:

compact (take 1) (drop 2) (++) [1,2,3,4] == [1,3,4]
compact (+10) (*2) (<) 11 == True
compact (+10) (*2) (<) 9 == False

Upvotes: 2

Views: 106

Answers (2)

behzad.nouri
behzad.nouri

Reputation: 77941

If you reorder the signature to:

(b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d

this is equivalent to liftM2, since ((->) r) is an instance of Monad type class

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r

and

\> liftM2 (++) (take 1) (drop 2) [1, 2, 3, 4]
[1,3,4]

similarly, liftA2 from Control.Applicative:

liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c

\> liftA2 (++) (take 1) (drop 2) [1, 2, 3, 4]
[1,3,4]

Upvotes: 5

Mark Anastos
Mark Anastos

Reputation: 365

liftM2 from Control.Monad is almost the same as your compact function, just with the arguments in a different order.

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r

which in context is the same as:

liftM2 :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d

So:

liftM2 (++) (take 1) (drop 2) [1,2,3,4] == [1,3,4]
liftM2 (<) (+10) (*2) 11 == True
liftM2 (<) (+10) (*2) 9 == False

Upvotes: 4

Related Questions