jbe*_*man 20 monads haskell typeclass
这个问题在设计代码中已经出现过几次,特别是库.似乎有一些兴趣,所以我认为它可能会成为一个很好的社区维基.
failMonad中的方法被一些人认为是疣; 这个课程有点武断,不是来自原始范畴理论.但当然在当前状态下,许多Monad类型都有逻辑和有用的fail实例.
MonadPlus类是Monad的一个子类,它提供了mzero一种在monad中逻辑地封装失败概念的方法.
因此,想要编写一些执行某种失败处理fail的monadic代码的库设计人员可以选择让他的代码使用Monad中的方法或将他的代码限制为MonadPlus类,这样他就可以感觉良好的使用mzero,即使他完全不关心幺半群组合mplus操作.
关于这个主题的一些讨论在这个维基页面中有关改进MonadPlus课程的建议.
所以我想我有一个具体的问题:
什么monad实例,如果有的话,有一个自然的fail方法,但不能是MonadPlus的实例,因为它们没有逻辑实现mplus?
但我最感兴趣的是关于这个问题的讨论.谢谢!
编辑:最后一个想法发生在我身上.我最近学到了(尽管它在文档中是正确的fail),monadic"do"符号以模式匹配失败的方式被贬低,就像(x:xs) <- return []调用monad一样fail.
似乎语言设计者必须受到一些自动故障处理的前景的强烈影响,这些故障处理内置于haskell的语法中,包含fail在Monad中.
fuz*_*fuz 10
想一想Either.它的monadic实例看起来像这样:
{-# LANGUAGE FlexibleInstances #-}
instance Monad (Either String) where
(Left x) >>= _ = Left x
(Right a) >>= f = f a
return = Right
fail = Left
Run Code Online (Sandbox Code Playgroud)
(我们需要FlexibleInstances以便允许一个实例Either String)
因此,Maybe如果发生某些事情,它基本上就像一个可选的错误消息.您无法重新创建此项mzero,因为您无法向失败添加错误消息.它有点不同fail.
每个实例都mplus应该满足这两个定律:
mzero `mplus` a -> a
a `mplus` mzero -> a
Run Code Online (Sandbox Code Playgroud)
简单,不是吗?但这些法律mplus特别重要.有了它们,就可MonadPlus以为它编写一个合理的实例:
instance MonadPlus (Either a) where
mzero = Left undefined
mplus (Left _) b = b
mplus a _ = a
Run Code Online (Sandbox Code Playgroud)
这是什么?它代表了一种选择.如果第一次计算成功,则返回.否则,mplus返回第二个计算.请注意它与(>>)不符合法律的不同之处:
Left a >> Right b -> Left a
Left a `mplus` Right b -> Right b
Run Code Online (Sandbox Code Playgroud)
(>>)将在第一次计算时停止,而mplus尝试第二次计算.[]也表现得像这样:
[] >> [1..4] -> []
[] `mplus` [1..4] -> [1,2,3,4]
Run Code Online (Sandbox Code Playgroud)
这只是为了讨论方面,MonadPlus特别是与之mplus相反的方面(>>).