In functional programming, functions are not so different from numbers or any other kind of value. Really the only difference is that the way you use a function is by applying it to an argument.
A value of type Maybe a
is either the value Nothing
or it is Just x
, where x
is of type a
. So if you have a value of type Maybe (a -> a)
, like your foo
, it is either Nothing
, or it is Just f
where f
is a function a -> a
. In the least fancy way, you would use it like this:
case foo of
Nothing -> "There was no function"
Just f -> "There was a function, and its value at 0 is " ++ show (f 0)
So if it turns out that foo
is not Nothing
, then it contains Just
a function as its value.
@Erich is right that especially the literal expression f (a -> b)
is likely to be related to applicative functors, but that is not necessarily so. For example, a favorite type of mine is the type of isomorphisms -- equivalences between two types:
data Iso a b = Iso (a -> b) (b -> a)
Iso
isn't even a Functor
(a prerequisite of Applicative
), but it is still quite useful. It turns out that pairs are equivalent to functions from Bool
. We could construct such an equivalence as an Iso
value:
pairEquiv :: Iso (a,a) (Bool -> a)
pairEquiv =
Iso (\(x,y) -> \b -> if b then x else y) -- from pair to function
(\f -> (f True, f False)) -- from function to pair
Here (Bool -> a)
appears as an argument to a type constructor, and it just means that if you give the Iso
a pair, it will give you a function back, and vice versa.