marcosh
marcosh

Reputation: 9008

Using Applicative instance of composed functors

I have two functions of the form

foo :: Int -> IO String

bar :: Int -> IO Integer

which basically live in the functor given by the composition of (->) Int and IO. Now, having a function of type

baz :: String -> Integer -> Float

I would like to lift it to the Int -> IO _ context using applicative syntax like

foobarbaz :: Int -> IO Float
foobarbaz = baz <$> foo <*> bar

If I do this the compiler yells at me with

Couldn't match type `IO String' with `[Char]'
      Expected type: Int -> String
        Actual type: Int -> IO String

as if it was trying to use the applicative instance only for (->) Int.

I thought applicative functors composed, so that I could use the applicative instance for the composed functor. Am I wrong? Or should I just provide more information to the compiler?

I tried also to enable TypeApplications to specify explicitly the functor I want to use, but I realized that I can't write (->) Int (IO _). Is there actually a way to do it?

Upvotes: 2

Views: 176

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

I thought applicative functors composed, so that I could use the applicative instance for the composed functor.

That is correct, but imagine that we take f ~ (->) Int, then the types are (<$>) :: (a -> b) -> (Int -> a) -> (Int -> b), and (<*>) :: (Int -> (a -> b)) -> (Int -> a) -> (Int -> b), but this does not match with the types since, baz requires a String and an Integer, whereas foo returns an IO String and bar an IO Integer.

You can make use of liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c to lift the baz function to use the result of IO actions:

import Control.Applicative(liftA2)

foobarbaz :: Int -> IO Float
foobarbaz = liftA2 baz <$> foo <*> bar

liftA2 will here thus convert a baz :: String -> Integer -> Float, into a liftA2 baz :: IO String -> IO Integer -> IO Float. This is thus a function that then matches with the output types of foo and bar.

Upvotes: 3

Related Questions