Intrigued by (->) as instances of monad and functor

haskell

Solution

It can be a bit confusing at first, but one important concept to remember is that `(->)` is not a monad or functor, but `(->) r` is. `Monad` and `Functor` types all have the kind `* -> *`, so they only expect one type parameter.

What this means is that `fmap` for `(->) r` looks like

fmap g func = \x -> g (func x)

Which is also known as

fmap g func = g . func

which is just normal function composition! When you `fmap g` over `func`, you change the output type by applying `g` to it. In this case, if `func` has the type `a -> b`, `g` must have a type like `b -> c`.

The `Monad` instance is bit more interesting. It lets you use the result of a function application "before" that application has occurred. What helped me understand was seeing an example like

f :: Double -> (Double,Double)
f = do
    x1 <- (2*)
    x2 <- (2+)
    return (x1, x2)

> f 1.0
(2.0, 3.0)

What this does is apply the implicit argument to `f` to each of the functions on the right hand side of the binds. So if you pass in `1.0` to `f`, it will bind the value `2 * 1.0` to `x1` and binds `2 + 1.0` to `x2`, then returns `(x1, x2)`. It really makes it easy to apply a single argument to many subexpressions. This function is equivalent to

f' x = (2 * x, 2 + x)

Why is this useful? One common use is the `Reader` monad, which is simply a newtype wrapper around `(->) r`. The `Reader` monad makes it easy to apply a static global config across your application. You could write code like

myApp :: Reader Config ()
myApp = do
    config <- ask
    -- Use config here
    return ()

And then you run your application with `runReader myApp initialConfig`. You can easily write actions in the `Reader Config` monad, compose them, chain them together, and all of them have access to the global, readonly config. In addition, there's a companion `ReaderT` monad transformer which allows you to build it into your transformer stack, letting you have very complex applications that have easy access to static configuration.

Problem

I am quite intrigued by `(->)` when I looked up in information about `(->)` in ghci. It says, ``` data (->) a b -- Defined in `GHC.Prim` ``` So far so good, but then it gets very interesting when it says - ``` instance Monad ((->) r) -- Defined in `GHC.Base` instance Functor ((->) r) -- Defined in `GHC.Base` ``` What does this implicate? Why does GHC define it as an instance of a Monad, and Functor for `(->)`?

Original source