[Haskell-beginners] Functions as containers; implications on being a Monad ((->) r)

Gesh gesh at gesh.uni.cx
Sun Jun 5 00:10:47 UTC 2016


On 2016-06-04 19:56, Daniel Bergey wrote:
> I think "a functor is a container" is not so helpful.  It works OK for
> Maybe and List, but it doesn't seem helpful in understanding Either,
> Reader, Writer, State, Continuation, promises.
This is correct. However, a large class of types form what are called 
"Representable Functors".
These include Lists, Trees, ((->) r), etc.

A representable functor is any type f with an isomorphism `(f a ~ r -> 
a)` for some r.
For example, `Stream a ~ Natural -> a` under the isomorphism:
 > toFunction xs = \i -> xs !! i
 > toList f = fromList $ map f [0..]
> I *think* it's the case that for (r ->), there isn't anything we can do
> with the Monad instance that we can't do with Applicative.  If someone
> can confirm or refute that, I'd appreciate it.  That's of course not
> true in general for other monads.
Indeed, for any representable functor, this all follows from the fact 
that we can write a lawful
join from Reader's <*>. Letting `join m = flip ($) <*> m`, we have:
 > (join . pure) x = \r -> ($ r) (const x r) = \r -> x $ r = x
 > (join . fmap pure) x = \r -> ($ r) ((pure . x) r) = \r -> (const (x 
r)) r = \r -> x r = x
 > (join . fmap join) x = \r -> ($ r) ((join . x) r) = \r -> join (x r) 
r = \r -> (\s -> ($s) (x r s)) r
 >  = \r -> x r r r = \r -> ($r) (\s -> x s s) r = join (\s -> ($s) (x 
s)) = (join . join) x

Hence, given the applicative instance for Reader, we obtain the Monad 
instance for free.
Therefore, working under the isomorphism, we have the same for any 
representable functor.

In particular, this gives that Stream is a Monad, where return gives the 
constant stream and
join takes the diagonal of a stream of streams.

Again, as noted, this is more or less the only way in which the
"Functors/Applicatives/Monads are nice/nicer/nicest containers" analogy 
works.
There are more things in heaven and earth than are described in that 
analogy, but it's a start.

Hope this helps, and that it lacks errors/misleading material,
Gesh
P.S. Code for working with representable functors can be found in 
representable-functors.
Code for working with Streams can be found in streams. Both are on Hackage.


More information about the Beginners mailing list