Haskell的WriterMonad解构
来源:互联网 发布:菊正宗化妆水 知乎 编辑:程序博客网 时间:2024/06/07 06:20
问题导出
move i = do x <- left i tell "Go" y <- left x return y
其中
left i = writer ( x -1,"move left\t'):t tell "G0" :: MonadWriter [Char] m => m ()
问题
tell "Go"的上下文到底在哪里
我们一步步的解开
move :: Int -> Writer String Intmove i = do x <- left' i _ <- tell "GO\t" return x
我们把do展开
move i = let ok p = do tell "go" return p ok _ = fail ".." in writer ((i-1),"Move Left\t") >>= ok
展开tell
move' i = let ok p = do writer ((),"Go\t") return p ok _ = fail ".." in writer ((i-1),"Move Left\t") >>= ok
将let解构转换为where解构,暂时消除掉i
move i = writer ((i-1),"Move Left\t") >>= ok where ok p = do writer ((),"Go\t") return p
消除掉第二个do
move i = writer ((i-1),"Move Left\t") >>= ok where ok p = writer ((),"Go\t") >> return p
增加辅助函数,做最终转换
instance (Monoid w) => Monad (Writer w) where return x = Writer (x,mempty) (Writer (x,v)) >>= f = let (Writer ( y,v')) = fx in Writer (y, v `mappend` v')
temp ::Int -> Writer String Inttemp i = writer ((),"GO\t") >> return (i-1)move i = case runWriter(temp i) of (y,v') -> writer (y, "Move Left\t" `mappend` v') _ -> writer(0,mempty)
对于temp
的模拟,可以参看monad这里的对于>>
的实现,确实是使用了>>=
。这样既满足了需要串行运算上下文,又能保证丢弃了上文的M a的a,但是仍然可以把M传递给下文。而恰好,Writer
的声明形式是Writer String a
,这样可以把a丢弃掉,而把String传递给下文,达到了tell
要求的仅保留String内容,而忽略a
的内容.
结论:
可以看出,上下文首先是因为做了内部的do运算,得到的关键的Writer((),"Go")
,
之后把(i-1) 附属到了tell的结果上,然后再做外部运算,结束掉x <- left i
。
0 0
- Haskell的WriterMonad解构
- 变量的解构赋值-数组的解构
- 数组的解构赋值
- 对象的解构赋值
- 对象的解构赋值
- 数组的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 对象的解构赋值
- 数组的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- 变量的解构赋值
- IOS如何选择图片加载方式:imageNamed和imageWithContentsOfFile的区别
- MIPS交叉环境的建立
- React学习--使用babel
- react native Text 上无法指定borderWidth 等一系列属性
- oc命名规范
- Haskell的WriterMonad解构
- LED显示屏技术基本知识
- dhcp无法动态改变
- java堆栈(转)
- 获取服务器控件的方法-针对TextBox绝对管用
- yii2 api restful 验证 速度控制
- 读书感想
- 微软100道算法题------求子数组的最大和
- gridview实现垂直和水平布局的方法