(Inspired by this[1] reddit thread.)
When combining monadic and non-monadic code, I've often wished for a
magical combinator of type
(Monad m) => ((a -> b) -> c) -> (a -> m b) -> m c
which would let me inject a monadic function into a pure one, then
wrap the ultimate result to ensure that no nastiness escapes.
Now, I'm pretty sure that writing such a combinator as-is is
impossible. My question is, what restrictions/changes would be
necessary for a similar combinator to be definable and well-behaved?
(Obviously it would be impossible to ensure that the (m b)s get
chained in any particular order, for order-sensitive monads, but it
would be the caller's responsibility to ensure order-irrelevance in
this case.)
As a thought experiment, I imagined an implementation for IO using
unsafePerformIO. This makes it easy to give the injected function the
right type, and it's possible to use return to give the result the
correct type too. Unfortunately, the semantics fail: if the injected
function is used lazily, there's no way to ensure that the unsafe IO
actions actually take place before the rest of the IO-based program,
and it's possible for them to show up later than expected. I suspect
that even in a strict language, lambda-abstractions would cause
similar trouble.
[1] http://programming.reddit.com/info/2n6eh/comments
Stuart Cook