1
votes

Let's assume I have a function f in Haskell, It takes a Double and returns a Double, and I have function g that also takes a Double and returns a Double.

Now, I can apply f to g like this: f . g.

Now, let's take a higher-dimensional function f, that takes two Doubles and outputs one:
f :: Double -> Double -> Double
or
f :: (Double, Double) -> Double
And I have two g functions as well:
g1 :: Double -> Double, g2 :: Double -> Double

Now, I want to compose the functions to get something like:
composition x = f (g1 x) (g2 x)

Can this be achieved just by using the dot (.) operator?

2

2 Answers

3
votes

You can make use of liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c for this:

composition = liftA2 f g1 g2

Since a function is an applicative [src]:

instance Applicative ((->) r) where
    pure = const
    (<*>) f g x = f x (g x)
    liftA2 q f g x = q (f x) (g x)

and liftA2 is implemented as [src]:

liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)

this will thus be resolved to:

liftA2 f g1 g2 x = (<*>) (fmap f g1) g2 x
                 = (fmap f g1 <*> g2) x
                 = (f . g1 <*> g2) x
                 = (\fa ga xa -> fa xa (ga xa)) (f . g1) g2 x
                 = (f . g1) x (g2 x)
                 = f (g1 x) (g2 x)
2
votes

You can try this:

import Control.Arrow

composition = f . (g1 &&& g2)

(&&&) turns g1 :: a -> b and g2 :: a -> c into g1 &&& g2 :: a -> (b, c). Then you can apply normal composition.