具有“真实”返回功能的monad
一个常见的初学者的错误是看到return
并认为它是一个语言关键字,它以返回值退出当前函数。 当然,我们知道这不是它所做的。 但我想知道......我们能否真的做出这样的功能? 纯粹为了论证的缘故,在这一点上。
看来我们正在寻找一些具有功能的monad Foo
exit :: x -> Foo x
这将中止其余的计算并立即返回x
。
这样的事情是可以修复的吗? 如果可以构建,它会有用吗? 这是一种理智的尝试吗?
是的,在Cont
单元中是可能的。 Cont
的定义如下:
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
现在我们可以创建如下exit
:
exit = Cont . const
事实上,你可以在几乎任何单子(例如,你可以做到这一点在做Either
单子,但是不在State
单子)。 然而, Cont
monad是所有monad的母亲:http://blog.sigfpe.com/2008/12/mother-of-all-monads.html
当然这是可行的。 它甚至已经在标准库中。 你只需要一个稍微清晰的类型签名。
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"
重要的是要注意的是,救助时给出的类型不是免费的 - 它必须与Either的类型相匹配。
看来你可以实现这一点:
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
注意单子如何有一个额外的类型参数; 我认为这是可以避免的。 基本上Foo ex
产生一个x
并且将“最终”产生一个e
。 请注意, run
功能需要两种类型匹配; 你也可以同样要求run
只在exit
被称为某处或其他几种可能性之一时才起作用。
所以,是的,你可以构建这个,不,它不是特别有用的AFAIK。
链接地址: http://www.djcxy.com/p/43363.html