haskell - 可以递归做脱糖吗
问题描述
可以将递归执行语句脱糖为一系列>>=
语句吗?如果是这样,当它被脱糖时,反向状态单子的定义是>>=
什么样的?
instance MonadFix m => Monad (StateT s m) where
return x = ...
m >>= f = StateT $ \s -> do
rec
(x, s'') <- runStateT m s'
(x', s') <- runStateT (f x) s
return (x', s'')
解决方案
Recursive-do 不仅对一系列>>=
调用进行去糖,而且只要确实存在递归,就对调用进行去糖mfix
。正是在mfix
调用中,整个递归发生,通过技术上称为“魔法仙尘”的东西。
说真的,每个 monad 的发生方式都不同,这就是为什么它是一个类MonadFix
而不仅仅是一个函数。但重要的一点是它可以“神奇地”将你自己的结果作为参数传递给你,这只是由于 Haskell 的懒惰,因此必须小心处理。
一般来说,是这样的:
do
rec
x <- f y
y <- g x
return $ h x y
脱糖成这个:
mfix (\ ~(x, y) -> do
x' <- f y
y' <- g x'
return (x', y')
)
>>= (\(x, y) -> h x y)
所以应用于反向状态定义,它看起来像这样:
m >>= f = StateT $ \s ->
mfix (\ ~((x, s''), (x',s')) -> do
(x0, s0'') <- runStateT m s'
(x0', s0') <- runStateT (f x0) s
return ((x0, s0''), (x0', x0'))
)
>>= (\(x, s''), (x',s') -> return (x', s''))
从这里,我们可以do
像往常一样对常规进行脱糖:
m >>= f = StateT $ \s ->
mfix (\ ~((x, s''), (x',s')) ->
runStateT m s' >>= \(x0, s0'') ->
runStateT (f x0) s >>= \(x0', s0') ->
return ((x0, s0''), (x0', x0'))
)
>>= (\(x, s''), (x',s') -> return (x', s''))
(也就是说,除非我搞砸了——很多蜱虫飞来飞去:-)
推荐阅读
- css - 更改嵌套 div 内鼠标悬停时图层的颜色
- list - How to filter in Prolog with SWISH
- angular - 如何覆盖 cdk-mouse-focused 和 cdk-focused
- python - 在 Python 列中对对应的行值进行分组
- android - Facebook 广告仅在从 Play 商店下载的应用中显示
- angular - angular4多文件上传第二组文件清空
- java - 可重入锁的表现在哪里?
- php - 无法在 PHP 中将上传文件名保存到 SQL
- node.js - Nodejs:进行http请求调用并将结果更新到mongoDB
- c - 在 C 中强制转换函数指针返回类型