我有以下代码:
import Control.Monad
coin :: MonadPlus m => m Int
coin = return 0 `mplus` return 1
Run Code Online (Sandbox Code Playgroud)
如果我对coin :: Maybe Int
解释器进行评估,它会受到影响Just 0
.这是正常的,因为Maybe的实现是MonadPlus的实例.
如果我coin :: [Int]
在解释器上进行评估,则打印出来[0, 1]
,因为mplus
列表的实现是一个append
.
但如果我评估coin
,没有任何类型装饰器,它打印0
.为什么?口译员"转换"什么类型coin
来评估它?
此代码摘自:http://homes.sice.indiana.edu/ccshan/rational/S0956796811000189a.pdf
实例MonadPlus IO
是唯一的,因为mzero
抛出:
Prelude Control.Monad> mzero
*** Exception: user error (mzero)
Run Code Online (Sandbox Code Playgroud)
因此,相应地,这也MonadPlus IO
意味着它也适用于错误。
mzero
如果其他动作不抛出,则显然用作标识元素:
Prelude Control.Monad> mzero `mplus` return 0
0
Prelude Control.Monad> return 0 `mplus` mzero
0
Run Code Online (Sandbox Code Playgroud)
但是当两个动作都抛出时不是这样:
Prelude Control.Monad> fail "Hello, world!" `mplus` mzero
*** Exception: user error (mzero)
Prelude Control.Monad> mzero `mplus` fail "Hello, world!"
*** Exception: user error (Hello, world!)
Run Code Online (Sandbox Code Playgroud)
所以MonadPlus IO
不是monoid。
如果MonadPlus
在用户意图出错时违反法律,那么它的实际意图是什么?
我正在尝试学习Haskell的基础知识,同时为Pandoc开发一个过滤器,以递归方式包含其他markdown文件.
基于脚本指南,我能够创建一个有点工作的过滤器.这将查找带有include
类的CodeBlocks 并尝试包含引用文件的AST.
```include
section-1.md
section-2.md
#pleasedontincludeme.md
```
Run Code Online (Sandbox Code Playgroud)
整个过滤器和输入源可以在以下存储库中找到:steindani/pandoc-include(或见下文)
可以使用过滤器运行pandoc,并使用以下命令以markdown格式查看输出: pandoc -t json input.md | runhaskell IncludeFilter.hs | pandoc --from json --to markdown
我注意到map
函数(在第38行) - 尽管获取要包含的文件列表 - 只调用第一个元素的函数.这不是唯一奇怪的行为.包含的文件也可以包含一个处理的包含块,并包含引用的文件; 但它不会更深入,忽略最后一个文件的包含块.
为什么map函数不遍历整个列表?为什么它在2级层次结构后停止?
请注意,我刚刚开始学习Haskell,我确信我犯了错误,但我很高兴学习.
谢谢
完整源代码:
module Text.Pandoc.Include where
import Control.Monad
import Data.List.Split
import Text.Pandoc.JSON
import Text.Pandoc
import Text.Pandoc.Error
stripPandoc :: Either PandocError Pandoc -> [Block]
stripPandoc p =
case p of
Left _ -> [Null]
Right (Pandoc _ blocks) -> blocks
ioReadMarkdown :: String …
Run Code Online (Sandbox Code Playgroud)