Composing Monadic Functions with `<=<` - haskell

I'm trying to understand the <=< function:
ghci> :t (<=<)
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
As I understand it, I give it 2 functions and an a, and then I'll get an m c.
So, why doesn't this example compile?
import Control.Monad
f :: a -> Maybe a
f = \x -> Just x
g :: a -> [a]
g = \x -> [x]
foo :: Monad m => a -> m c
foo x = f <=< g x
For foo 3, I would expect Just 3 as a result.
But I get this error:
File.hs:10:15:
Couldn't match expected type `a0 -> Maybe c0'
with actual type `[a]'
In the return type of a call of `g'
Probable cause: `g' is applied to too many arguments
In the second argument of `(<=<)', namely `g x'
In the expression: f <=< g x Failed, modules loaded: none.

There are two errors here.
First, (<=<) only composes monadic functions if they share the same monad. In other words, you can use it to compose two Maybe functions:
(<=<) :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c)
... or two list functions:
(<=<) :: (b -> [c]) -> (a -> [b]) -> (a -> [c])
... but you cannot compose a list function and maybe function this way. The reason for this is that when you have a type signature like this:
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
... the compiler will ensure that all the ms must match.
The second error is that you forgot to parenthesize your composition. What you probably intended was this:
(f <=< g) x
... if you omit the parentheses the compiler interprets it like this:
f <=< (g x)
An easy way to fix your function is just to define a helper function that converts Maybes to lists:
maybeToList :: Maybe a -> [a]
maybeToList Nothing = []
maybeToList (Just a) = [a]
This function actually has the following two nice properties:
maybeToList . return = return
maybeToList . (f <=< g) = (maybeToList . f) <=< (maybeToList . g)
... which are functor laws if you treat (maybeToList .) as analogous to fmap and treat (<=<) as analogous to (.) and return as analogous to id.
Then the solution becomes:
(maybeToList . f <=< g) x

Note that, in
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
m is static -- You're trying to substitute both [] and Maybe for m in the definition -- that won't type check.
You can use <=< to compose functions of the form a -> m b where m is a single monad. Note that you can use different type arguments though, you don't need to be constrained to the polymorphic a.
Here's an example of using this pattern constrained to the list monad:
f :: Int -> [Int]
f x = [x, x^2]
g :: Int -> [String]
g 0 = []
g x = [show x]
λ> :t g <=< f
g <=< f :: Int -> [String]
λ> g <=< f $ 10
["10","100"]

You can't mix monads together. When you see the signature
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
The Monad m is only a single Monad, not two different ones. If it were, the signature would be something like
(<=<) :: (Monad m1, Monad m2) => (b -> m2 c) -> (a -> m1 b) -> a -> m2 c
But this is not the case, and in fact would not really be possible in general. You can do something like
f :: Int -> Maybe Int
f 0 = Just 0
f _ = Nothing
g :: Int -> Maybe Int
g x = if even x then Just x else Nothing
h :: Int -> Maybe Int
h = f <=< g

Related

How can I avoid explicit recursion in this case?

I wound up with this skeleton:
f :: (Monad m) => b -> m ()
f x = traverse_ (f . g x) =<< h x -- how avoid explicit recursion?
g :: b -> a -> b
-- h :: (Foldable t) => b -> m (t a) -- why "Could not deduce (Foldable t0) arising from a use of ‘traverse_’"
h :: b -> m [a]
How can I avoid the explicit recursion in f?
Bonus: When I try to generalize h from [] to Foldable, f does not type check (Could not deduce (Foldable t0) arising from a use of ‘traverse_’) -- what am I doing wrong?
UPDATE:
Here's the real code. The Right side is for recursing down directories of security camera footage whose names are integers. Left is the base case to process leaves whose names are not integers.
a <|||> b = left a . right b
doDir (Right d) = traverse_ (doDir . doInt) =<< listDirectory d
where doInt s = ((<|||>) <$> (,) <*> const) (d </> s) $ (TR.readEither :: String -> Either String Int) s
f = doDir and g ~ doInt but got refactored a little. h = listDirectory. to answer the bonus, i was just being silly and wasn't seeing that i had to combine all the definitions to bind the types together:
f :: (Monad m, Foldable t) => (b -> a -> b) -> (b -> m (t a)) -> b -> m ()
f g h x = traverse_ (f g h . g x) =<< h x
If you don't mind leaking a bit of memory building a Tree and then throwing it away, you can use unfoldTreeM:
f = unfoldTreeM (\b -> (\as -> ((), g b <$> as)) <$> h b)
I do not believe there is a corresponding unfoldTreeM_, but you could write one (using explicit recursion). To generalize beyond the Tree/[] connection, you might also like refoldM; you can find several similar functions if you search for "hylomorphism" on Hackage.

How does <*> derived from pure and (>>=)?

class Applicative f => Monad f where
return :: a -> f a
(>>=) :: f a -> (a -> f b) -> f b
(<*>) can be derived from pure and (>>=):
fs <*> as =
fs >>= (\f -> as >>= (\a -> pure (f a)))
For the line
fs >>= (\f -> as >>= (\a -> pure (f a)))
I am confused by the usage of >>=. I think it takes a functor f a and a function, then return another functor f b. But in this expression, I feel lost.
Lets start with the type we're implementing:
(<*>) :: Monad f => f (a -> b) -> f a -> f b
(The normal type of <*> of course has an Applicative constraint, but here we're trying to use Monad to implement Applicative)
So in fs <*> as = _, fs is an "f of functions" (f (a -> b)), and as is an "f of as".
We'll start by binding fs:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= _
If you actually compile that, GHC will tell us what type the hole (_) has:
foo.hs:4:12: warning: [-Wtyped-holes]
• Found hole: _ :: (a -> b) -> f b
Where: ‘a’, ‘f’, ‘b’ are rigid type variables bound by
the type signature for:
(Main.<*>) :: forall (f :: * -> *) a b.
Monad f =>
f (a -> b) -> f a -> f b
at foo.hs:2:1-45
That makes sense. Monad's >>= takes an f a on the left and a function a -> f b on the right, so by binding an f (a -> b) on the left the function on the right gets to receive an (a -> b) function "extracted" from fs. And provided we can write a function that can use that to return an f b, then the whole bind expression will return the f b we need to meet the type signature for <*>.
So it'll look like:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> _)
What can we do there? We've got f :: a -> b, and we've still got as :: f a, and we need to make an f b. If you're used to Functor that's obvious; just fmap f as. Monad implies Functor, so this does in fact work:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> fmap f as)
It's also, I think, a much easier way to understand the way Applicative can be implemented generically using the facilities from Monad.
So why is your example written using another >>= and pure instead of just fmap? It's kind of harkening back to the days when Monad did not have Applicative and Functor as superclasses. Monad always "morally" implied both of these (since you can implement Applicative and Functor using only the features of Monad), but Haskell didn't always require there to be these instances, which leads to books, tutorials, blog posts, etc explaining how to implement these using only Monad. The example line given is simply inlining the definition of fmap in terms of >>= and pure (return)1.
I'll continue to unpack as if we didn't have fmap, so that it leads to the version you're confused by.
If we're not going to use fmap to combine f :: a -> b and as :: f a, then we'll need to bind as so that we have an expression of type a to apply f to:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> as >>= (\a -> _))
Inside that hole we need to make an f b, and we have f :: a -> b and a :: a. f a gives us a b, so we'll need to call pure to turn that into an f b:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> as >>= (\a -> pure (f a)))
So that's what this line is doing.
Binding fs :: f (a -> b) to get access to an f :: a -> b
Inside the function that has access to f it's binding as to get access to a :: a
Inside the function that has access to a (which is still inside the function that has access to f as well), call f a to make a b, and call pure on the result to make it an f b
1 You can implement fmap using >>= and pure as fmap f xs = xs >>= (\x -> pure (f x)), which is also fmap f xs = xs >>= pure . f. Hopefully you can see that the inner bind of your example is simply inlining the first version.
Applicative is a Functor. Monad is also a Functor. We can see the "Functorial" values as standing for computations of their "contained" ⁄ produced pure values (like IO a, Maybe a, [] a, etc.), as being the allegories of ⁄ metaphors for the various kinds of computations.
Functors describe ⁄ denote notions ⁄ types of computations, and Functorial values are reified computations which are "run" ⁄ interpreted in a separate step which is thus akin to that famous additional indirection step by adding which, allegedly, any computational problem can be solved.
Both fs and as are your Functorial values, and bind ((>>=), or in do notation <-) "gets" the carried values "in" the functor. Bind though belongs to Monad.
What we can implement in Monad with (using return as just a synonym for pure)
do { f <- fs ; -- fs >>= ( \ f -> -- fs :: F (a -> b) -- f :: a -> b
a <- as ; -- as >>= ( \ a -> -- as :: F a -- a :: a
return (f a) -- return (f a) ) ) -- f a :: b
} -- :: F b
( or, with MonadComprehensions,
[ f a | f <- fs, a <- as ]
), we get from the Applicative's <*> which expresses the same computation combination, but without the full power of Monad. The difference is, with Applicative as is not dependent on the value f there, "produced by" the computation denoted by fs. Monadic Functors allow such dependency, with
[ bar x y | x <- xs, y <- foo x ]
but Applicative Functors forbid it.
With Applicative all the "computations" (like fs or as) must be known "in advance"; with Monad they can be calculated -- purely -- based on the results of the previous "computation steps" (like foo x is doing: for (each) value x that the computation xs will produce, new computation foo x will be (purely) calculated, the computation that will produce (some) y(s) in its turn).
If you want to see how the types are aligned in the >>= expressions, here's your expression with its subexpressions named, so they can be annotated with their types,
exp = fs >>= g -- fs >>=
where g f = xs >>= h -- (\ f -> xs >>=
where h x = return (f x) -- ( \ x -> pure (f x) ) )
x :: a
f :: a -> b
f x :: b
return (f x) :: F b
h :: a -> F b -- (>>=) :: F a -> (a -> F b) -> F b
xs :: F a -- xs h
-- <-----
xs >>= h :: F b
g f :: F b
g :: (a -> b) -> F b -- (>>=) :: F (a->b) -> ((a->b) -> F b) -> F b
fs :: F (a -> b) -- fs g
-- <----------
fs >>= g :: F b
exp :: F b
and the types of the two (>>=) applications fit:
(fs :: F (a -> b)) >>= (g :: (a -> b) -> F b)) :: F b
(xs :: F a ) >>= (h :: (a -> F b)) :: F b
Thus, the overall type is indeed
foo :: F (a -> b) -> F a -> F b
foo fs xs = fs >>= g -- foo = (<*>)
where g f = xs >>= h
where h x = return (f x)
In the end, we can see monadic bind as an implementation of do, and treat the do notation
do {
abstractly, axiomatically, as consisting of the lines of the form
a <- F a ;
b <- F b ;
......
n <- F n ;
return (foo a b .... n)
}
(with a, F b, etc. denoting values of the corresponding types), such that it describes the overall combined computation of the type F t, where foo :: a -> b -> ... -> n -> t. And when none of the <-'s right-hand side's expressions is dependent on no preceding left-hand side's variable, it's not essentially Monadic, but just an Applicative computation that this do block is describing.
Because of the Monad laws it is enough to define the meaning of do blocks with just two <- lines. For Functors, just one <- line is allowed ( fmap f xs = do { x <- xs; return (f x) }).
Thus, Functors/Applicative Functors/Monads are EDSLs, embedded domain-specific languages, because the computation-descriptions are themselves values of our language (those to the right of the arrows in do notation).
Lastly, a types mandala for you:
T a
T (a -> b)
(a -> T b)
-------------------
T (T b)
-------------------
T b
This contains three in one:
F a A a M a
a -> b A (a -> b) a -> M b
-------------- -------------- -----------------
F b A b M b
You can define (<*>) in terms of (>>=) and return because all monads are applicative functors. You can read more about this in the Functor-Applicative-Monad Proposal. In particular, pure = return and (<*>) = ap is the shortest way to achieve an Applicative definition given an existing Monad definition.
See the type signatures for (<*>), ap and (>>=):
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
ap :: Monad m => m (a -> b) -> m a -> m b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
The type signature for (<*>) and ap are nearly equivalent. Since ap is written using do-notation, it is equivalent to some use of (>>=). I'm not sure this helps, but I find the definition of ap readable. Here's a rewrite:
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
≡ ap m1 m2 = do
x1 <- m1
x2 <- m2
return (x1 x2)
≡ ap m1 m2 =
m1 >>= \x1 ->
m2 >>= \x2 ->
return (x1 x2)
≡ ap m1 m2 = m1 >>= \x1 -> m2 >>= \x2 -> return (x1 x2)
≡ ap mf ma = mf >>= (\f -> ma >>= (\a -> pure (f a)))
Which is your definition. You could show that this definition upholds the applicative functor laws, since not everything defined in terms of (>>=) and return does that.

Haskell Syntax: How are functions combined together?

a line from FileIO.hs in Functional Programming Course exercise
getFile :: FilePath -> IO (FilePath, Chars)
getFile = lift2 (<$>) (,) readFile
According to its type signature, getFile returns IO ( FilePath, Chars), which means a tuple of filename and its content.
But I just can't figure out why it turns that way.
Why does FilePath turn out unchanged in the left, and readFile filename filled in the right?
Is (,) an Applicative instance too? (,) is not an IO, so what did lift2 lift?
And, is there a way to derive those type signatures and get proved?
The syntax I know is that a function follows by its arguments, and it eats one argument on its right hand and becomes a new function. But when it comes to code like that, it looks just like a magic cube to me...
Thank you for helping me out!
Ps. Extra Information as follows
instance Functor IO where
(<$>) =
P.fmap
lift2 ::
Applicative f =>
(a -> b -> c)
-> f a
-> f b
-> f c
lift2 f a b =
f <$> a <*> b
getFiles :: List FilePath -> IO (List (FilePath, Chars))
getFiles = sequence . (<$>) getFile
Let's look at
lift2 (<$>) (,) readFile
This is indeed straightforward function application:
((lift2 (<$>)) (,)) readFile
(or lift2 being applied to three arguments).
The types involved (with uniquely renamed type variables to reduce confusion) are:
lift2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
(<$>) :: (Functor g) => (j -> k) -> g j -> g k
(,) :: m -> n -> (m, n)
readFile :: FilePath -> IO Chars
The first thing in our expression is applying lift2 to (<$>). That means we need to unify a -> b -> c (type of lift2's first argument) and (Functor g) => (j -> k) -> g j -> g k (type of <$>) somehow.
That is:
a -> b -> c = (j -> k) -> g j -> g k
-- where g is a Functor
a = j -> k
b = g j
c = g k
This works out. The result type is
f a -> f b -> f c
-- where f is an Applicative
which is
f (j -> k) -> f (g j) -> f (g k)
Now this expression (lift2 (<$>)) is applied to (,). Again we have to make the types line up:
f (j -> k) = m -> n -> (m, n)
Here we make use of the property that -> is right associative (i.e. a -> b -> c means a -> (b -> c)) and that we can use (curried) prefix notation in types (i.e. a -> b is the same as (->) a b, which is the same as ((->) a) b).
f (j -> k) = ((->) m) (n -> (m, n))
f = (->) m
j = n
k = (m, n)
This also works out. The result type is
f (g j) -> f (g k)
which (after substituting) becomes
((->) m) (g n) -> ((->) m) (g (m, n))
(m -> g n) -> (m -> g (m, n))
This expression (lift2 (<$>) (,)) is applied to readFile. Again, making the types line up:
m -> g n = FilePath -> IO Chars
m = FilePath
g = IO
n = Chars
And substituting into the result type:
m -> g (m, n)
FilePath -> IO (FilePath, Chars)
This is the type of the whole lift2 (<$>) (,) readFile expression. As expected, it matches the declaration of getFile :: FilePath -> IO (FilePath, Chars).
However, we still need to verify that our class constraints (Functor g, Applicative f) are resolved.
g is IO, which is indeed a Functor (as well as Applicative and Monad). There are no big surprises here.
f is more interesting: f = (->) m, so we need to look for an Applicative instance for (->) m. Such an instance does in fact exist, and its definition contains the answer to what getFile actually does.
We can derive what the instance must look like by just looking at the type of lift2 (as used in getFile):
lift2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
lift2 :: (a -> b -> c) -> ((->) m) a -> ((->) m) b -> ((->) m) c
lift2 :: (a -> b -> c) -> (m -> a) -> (m -> b) -> (m -> c)
lift2 :: (a -> b -> c) -> (m -> a) -> (m -> b) -> m -> c
I.e. lift2 takes
a function that combines an a and a b into a c,
a function that transforms an m into an a,
a function that transforms an m into a b,
and an m,
and produces a c.
The only way it can do that is by passing the m into the second and third functions and combining their results using the first function:
lift2 f g h x = f (g x) (h x)
If we inline this definition in getFile, we get
getFile = lift2 (<$>) (,) readFile
getFile = \x -> (<$>) ((,) x) (readFile x)
getFile = \x -> (,) x <$> readFile x
Excercise for the reader:
lift2 is actually defined in terms of <$> and <*>. What are the types of <$> and <*> in the Applicative instance of (->) m? What must their definition look like?

How does ap fromMaybe compose?

There I was, writing a function that takes a value as input, calls a function on that input, and if the result of that is Just x, it should return x; otherwise, it should return the original input.
In other words, this function (that I didn't know what to call):
foo :: (a -> Maybe a) -> a -> a
foo f x = fromMaybe x (f x)
Since it seems like a general-purpose function, I wondered if it wasn't already defined, so I asked on Twitter, and Chris Allen replied that it's ap fromMaybe.
That sounded promising, so I fired up GHCI and started experimenting:
Prelude Control.Monad Data.Maybe> :type ap
ap :: Monad m => m (a -> b) -> m a -> m b
Prelude Control.Monad Data.Maybe> :type fromMaybe
fromMaybe :: a -> Maybe a -> a
Prelude Control.Monad Data.Maybe> :type ap fromMaybe
ap fromMaybe :: (b -> Maybe b) -> b -> b
The type of ap fromMaybe certainly looks correct, and a couple of experiments seem to indicate that it has the desired behaviour as well.
But how does it work?
The fromMaybe function seems clear to me, and in isolation, I think I understand what ap does - at least in the context of Maybe. When m is Maybe, it has the type Maybe (a -> b) -> Maybe a -> Maybe b.
What I don't understand is how ap fromMaybe even compiles. To me, this expression looks like partial application, but I may be getting that wrong. If this is the case, however, I don't understand how the types match up.
The first argument to ap is m (a -> b), but fromMaybe has the type a -> Maybe a -> a. How does that match? Which Monad instance does the compiler infer that m is? How does fromMaybe, which takes two (curried) arguments, turn into a function that takes a single argument?
Can someone help me connect the dots?
But that use of ap is not in the context of Maybe. We're using it with a function, fromMaybe, so it's in the context of functions, where
ap f g x = f x (g x)
Among the various Monad instances we have
instance Monad ((->) r)
so it is
ap :: Monad m => m (a -> b) -> m a -> m b
fromMaybe :: r -> (Maybe r -> r)
ap :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
ap f g x :: b
ap fromMaybe :: (r -> a) -> (r -> b) , a ~ Maybe r , b ~ r
because -> in types associates to the right: a -> b -> c ~ a -> (b -> c). Trying to plug the types together, we can only end up with that definition above.
And with (<*>) :: Applicative f => f (a -> b) -> f a -> f b, we can write it as (fromMaybe <*>), if you like this kind of graffiti:
#> :t (fromMaybe <*>)
(fromMaybe <*>) :: (r -> Maybe r) -> r -> r
As is rightfully noted in another answer here, when used with functions, <*> is just your good ole' S combinator. We can't very well have function named S in Haskell, so <*> is just a part of standard repertoire of the point-free style of coding. Monadic bind (more so, flipped), =<<, can be even more mysterious, but a pointfree coder just doesn't care and will happily use it to encode another, similar pattern,
(f =<< g) x = f (g x) x
in combinatory function calls, mystery or no mystery (zipWith (-) =<< drop 1 comes to mind).
Apologies for laconic and mechanical answer. I don't like cherry-picking things like Applicative or Monad, but I don't know where you're at. This is not my usual approach to teaching Haskell.
First, ap is really (<*>) under the hood.
Prelude> import Control.Monad
Prelude> import Data.Maybe
Prelude> import Control.Applicative
Prelude> :t ap
ap :: Monad m => m (a -> b) -> m a -> m b
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
What does this mean? It means we don't need something as "strong" as Monad to describe what we're doing. Applicative suffices. Functor doesn't, though.
Prelude> :info Applicative
class Functor f => Applicative (f :: * -> *) where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Prelude> :info Functor
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
Here's ap/(<*>) with the Maybe Monad/Applicative:
Prelude> ap (Just (+1)) (Just 1)
Just 2
Prelude> (<*>) (Just (+1)) (Just 1)
Just 2
First thing to figure out is, which instance of the typeclass Applicative are we talking about?
Prelude> :t fromMaybe
fromMaybe :: a -> Maybe a -> a
Desugaring fromMaybe's type a bit gives us:
(->) a (Maybe a -> a)
So the type constructor we're concerned with here is (->). What does GHCi tell us about (->) also known as function types?
Prelude> :info (->)
data (->) a b -- Defined in ‘GHC.Prim’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
Hrm. What about Maybe?
Prelude> :info Maybe
data Maybe a = Nothing | Just a -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Applicative Maybe -- Defined in ‘GHC.Base’
What happened with the use of (<*>) for Maybe was this:
Prelude> (+1) 1
2
Prelude> (+1) `fmap` Just 1
Just 2
Prelude> Just (+1) <*> Just 1
Just 2
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> let mFmap = fmap :: (a -> b) -> Maybe a -> Maybe b
Prelude> (+1) `mFmap` Just 1
Just 2
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude> let mAp = (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
Prelude> :t (+1)
(+1) :: Num a => a -> a
Prelude> :t Just (+1)
Just (+1) :: Num a => Maybe (a -> a)
Prelude> Just (+1) `mAp` Just 1
Just 2
Okay, what about the function type's Functor and Applicative? One of the tricky parts here is that (->) has be to be partially applied in the type to be a Functor/Applicative/Monad. So your f becomes (->) a of the overall (->) a b where a is an argument type and b is the result.
Prelude> (fmap (+1) (+2)) 0
3
Prelude> (fmap (+1) (+2)) 0
3
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> let funcMap = fmap :: (a -> b) -> (c -> a) -> c -> b
Prelude> -- f ~ (->) c
Prelude> (funcMap (+1) (+2)) 0
3
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude> let funcAp = (<*>) :: (c -> a -> b) -> (c -> a) -> (c -> b)
Prelude> :t fromMaybe
fromMaybe :: a -> Maybe a -> a
Prelude> :t funcAp fromMaybe
funcAp fromMaybe :: (b -> Maybe b) -> b -> b
Prelude> :t const
const :: a -> b -> a
Prelude> :t funcAp const
funcAp const :: (b -> b1) -> b -> b
Not guaranteed to be useful. You can tell funcAp const isn't interesting just from the type and knowing how parametricity works.
Edit: speaking of compose, the Functor for (->) a is just (.). Applicative is that, but with an extra argument. Monad is the Applicative, but with arguments flipped.
Further whuttery: Applicative <*> for (->) a) is S and pure is K of the SKI combinator calculus. (You can derive I from K and S. Actually you can derive any program from K and S.)
Prelude> :t pure
pure :: Applicative f => a -> f a
Prelude> :t const
const :: a -> b -> a
Prelude> :t const
const :: a -> b -> a
Prelude> let k = pure :: a -> b -> a
Prelude> k 1 2
1
Prelude> const 1 2
1
I'm going to relabel the type arguments, for clarity.
ap :: Monad m => m (a -> b) -> m a -> m b
fromMaybe :: c -> Maybe c -> c
Which Monad instance does the compiler infer that m is?
((->) r) is a Monad. This is all functions that have type r as their argument, for some specific r.
So in the type:
ap :: Monad m => m (a -> b) -> m a -> m b
m ~ (c ->), a ~ Maybe c and b ~ c.
The return type, m a -> m b, expands to (c -> Maybe c) -> c -> c - which is the type of ap fromMaybe.
The monad you are looking for is (->) r or r -> _ if you prefer infix syntax.
Then the signature of ap expands to:
m (a -> b) -> m a -> m b =
(r -> (a -> b)) -> (r -> a) -> r -> b = -- now we use the signature of fromMaybe
(b -> (Maybe b -> b)) -> (b -> Maybe b) -> b -> b
Now if you consider ap fromMaybe as a partially applied function and voila you get the desired result.

Implementing Applicative's (<*>) for Monad

Applicative's has the (<*>) function:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
Learn You a Haskell shows the following function.
Given:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap f m = do
g <- f -- '<-' extracts f's (a -> b) from m (a -> b)
m2 <- m -- '<-' extracts a from m a
return (g m2) -- g m2 has type `b` and return makes it a Monad
How could ap be written with bind alone, i.e. >>=?
I'm not sure how to extract the (a -> b) from m (a -> b). Perhaps once I understand how <- works in do notation, I'll understand the answer to my above question.
How could ap be written with bind alone, i.e. >>= ?
This is one sample implementation I can come up with:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap xs a = xs >>= (\f -> liftM f a)
Of if you don't want to even use liftM then:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap mf ma = mf >>= (\f -> ma >>= (\a' -> return $ f a'))
Intially these are the types:
mf :: m (a -> b)
ma :: m a
Now, when you apply bind (>>=) operator to mf: mf >>= (\f-> ..., then f has the type of:
f :: (a -> b)
In the next step, ma is also applied with >>=: ma >>= (\a'-> ..., here a' has the type of:
a' :: a
So, now when you apply f a', you get the type b from that because:
f :: (a -> b)
a' :: a
f a' :: b
And you apply return over f a' which will wrap it with the monadic layer and hence the final type you get will be:
return (f a') :: m b
And hence everything typechecks.

Resources