简体   繁体   中英

What does “f (a -> b)” type signature mean in Haskell?

I'm trying to understand applicatives in Haskell. Can't figure out what does following type signature mean:

f (a -> b)

For example:

foo :: Num a => Maybe (a -> a)
foo = Just (+1)

How can I understand the meaning of Maybe (a -> a) ? Is it a function? If it is, which types of arguments are allowed? Also obviously I'm new in functional programming, will be grateful for any resources on this topic.

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.

You can imagine f (a -> b) as a function of type a -> b wrapped in a context. It is mostly used in the context of Applicative s, that Maybe a is a prominent example for.

Applicative s are an extension of Functor s. A typical example for using Applicative s are functions with multiple arguments.

What if we have two Maybe Int s that we want to add up. We could try by partially applying + with fmap aka <$> . Thus we might try:

f :: Maybe (Int -> Int)
f = (+) <$> Just 3

But now, how do we apply this to a second argument. That's where we need the Applicative typeclass. It defines the <*> function. It has the type

<*> :: Applicative f => f (a -> b) -> f a -> f b

Thus we can use it to apply a second Maybe Int to our partially applied function f by doing:

> f <*> Just 4
Just 7

Without the helper function f the syntax resembles standard function application:

> (+) <$> Just 3 <*> Just 4
Just 7

For further reference see the chapter on applicative functors of learnyouahaskell.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM