A monad with a "real" return function
A common beginner's mistake is to see return
and think that it's a language keyword that exits the current function with a return value. Of course, we know that isn't what it does at all. But I wonder... could we actually make such a function? Purely for argument's sake, at this point.
It seems we're looking for some monad Foo
which possesses a function
exit :: x -> Foo x
which will abort the rest of the computation and immediately return x
.
Is such a thing constructable? If it could be constructed, would it be useful? Is this even a sane thing to attempt to do?
Yes, it is possible in the Cont
monad. The Cont
is defined as follows:
newtype Cont r a = Cont {runCont :: (a -> r) -> r}
instance Monad (Cont r) where
return a = Cont ($ a)
m >>= k = Cont $ c -> runCont m $ a -> runCont (k a) c
Now we can create exit
as follows:
exit = Cont . const
In fact you can do it in almost any monad (for example you could do it in the Either
monad but not in the State
monad). However the Cont
monad is the mother of all monads: http://blog.sigfpe.com/2008/12/mother-of-all-monads.html
Of course it's doable. It's even already in the standard libraries. You just need a slightly saner type signature.
import Control.Monad
exit :: a -> Either a b
exit = Left
main = print $ do
x <- Right 5
exit "foo"
error "this is a good place to crash"
The important thing to note is that the type given when bailing out isn't free - it has to match the type of the Either.
It appears you can just about implement this:
data Foo e x =
Next x |
Done e
instance Monad (Foo e) where
return = Next
(Next x) >>= f = f x
(Done e) >>= f = Done e
exit :: e -> Foo e x
exit = Done
run :: Foo x x -> x
run (Next x) = x
run (Done x) = x
Notice how the monad has an extra type parameter; I don't think it's possible to avoid this. Basically Foo ex
produces an x
and will "ultimately" produce an e
. Note that the run
function requires both types to match; you could equally demand that run
only works if exit
gets called somewhere, or one of a few other possibilities...
So, yes you can construct this, and no, it's not especially useful AFAIK.
链接地址: http://www.djcxy.com/p/43364.html上一篇: Haskell中Monad和Applicative的区别
下一篇: 具有“真实”返回功能的monad