Just my two cents on the gist of John Hughes' paper.
I would summarize the problem John is pointing to as
"the -> is not always what you want". This has mainly two reasons:
- evaluation is immediately abandonded once a closure is encountered
(it's too lazy)
- the -> is an abstract type which we cannot look into
- some built-in stuff is using it
This hits us partly in terms of efficiency and partly in terms of
applicability of concepts.
For example, we cannot define functions that carry some additional
information around: either its not a function, or we have to put the
additional info into the result which often violates the intention why
we wanted this info in the first place, e.g. to decide whether to use
that function or not.
John's solution is to turn -> into a class (or rather: provide a class
which uses an abstract concept rather than a concrete one whenever
it's suitable) of arrows. This makes it possible to stuff
additional info into arrows. It's almost as if he defined a category,
and I'm a bit surprised he did not. This would have looked as
follows:
class Category a where
(>>>) :: a b c -> a c d -> a b d
id :: a b b
Based on this, we could define monads w.r.t. this concept of category,
e.g.
class Category arr => CMonad m arr where
return :: b -> m arr b
(>>=) :: m arr b -> arr b (m arr c) -> m arr c
In this case, the second argument of >>= is not a function but an
arrow in a category which makes it possible for us to instantiate all
of this in such a way that static info can be squeezed out of the
arrow if our application demands that. Moreover, ordinary monads are
just a special case in which we instantiate -> as a Category.
This is a little different from John's idea which uses arrows as a
replacement for monads. I would argue that they are better suited to
replace the built-in functions, whilst we can maintain monads (albeit
generalised) in the usual format.
Stefan Kahrs