是否有一些理由为什么Prelude没有像这样定义列表monad?(注意非标准的实现>>.)
instance Monad [] where
m >>= k = concat (map k m)
m >> k = k -- a.k.a. flip const
return x = [x]
fail s = []
Run Code Online (Sandbox Code Playgroud)
我试图按照monad法律对此进行检查,但他们没有提及>>.在Monad类的定义是这样的:
m >> k = m >>= \_ -> k
Run Code Online (Sandbox Code Playgroud)
在[]实例中将转换为:
concat (map (\_ -> k) m)
Run Code Online (Sandbox Code Playgroud)
这当然不等于flip const- 比如,它们会产生明显不同的结果[1..5] >> return 1.但是我不清楚这个默认定义是否是必须遵守的实例的法则Monad,或者只是满足flip const实现也将满足的其他一些法律的默认实现.
直观地,考虑到列表monad 的意图("非确定性计算"),似乎替代定义>>将同样好,如果不是更好,这要归功于修剪分支,保证等于一个.或者另一种说法是,如果我们处理集合而不是列表,那么两个候选定义将是等价的.但是我在这里错过了一些微妙之处,这使得flip const列表的定义错了吗?
编辑:ehird的答案捕获了上面的一个非常明显的缺陷,即它得到了错误的预期结果[] >> k,应该是[],而不是k.不过,我认为这个问题可以修改为这个定义:
[] >> k = []
_ >> k = k
Run Code Online (Sandbox Code Playgroud)
ehi*_*ird 14
a >> b必须始终相当于a >>= const b; 它只在Monad类中,因此您可以定义更高效(但在语义上等效)的版本.这就是为什么它不是monad定律的一部分:它不是monad定义的一部分,只是类型类(如fail).
不幸的是,我在基础软件包的文档中找不到任何明确说明的基础软件包,但我认为旧版本可能已(>>)在Monad类型类之外定义.
对于它的价值,你的定义(>>)打破了monad用于非确定性计算的列表monad.既然[]用来代表失败,[] >> m必须永远[]; 在你耗尽所有可能的分支后,你不能继续!这也意味着这两个方案:
do { m; ... }
do { _ <- m; ... }
Run Code Online (Sandbox Code Playgroud)
可能会有不同的行为,因为前者与(>>)后者有关,后者与后者有关(>>=).(参见Haskell 2010报告.)
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |