Enr*_*lis 3 monads haskell functor do-notation io-monad
从LYAH我了解到这个do符号只是monadic风格的语法糖;从维基书中我读到的或多或少是一样的;所以我的理解是,do如果没有Monad实例,就不可能有任何符号。
然而,我阅读Functor了IO类型 ctor实例的这个定义。
instance Functor IO where
fmap f action = do
result <- action
return (f result)
Run Code Online (Sandbox Code Playgroud)
这只是以下内容的语法糖,不是吗?
instance Functor IO where
fmap f action = action >>= return . f
Run Code Online (Sandbox Code Playgroud)
这意味着下面的假设IO是Monadfirst 的实例;这与每个Monad都是一个Functor而不是相反的事实背道而驰。
事实上,我已经意识到 aMonad是“多于” an Applicative,而后者又是“多于” a Functor,这与对其实例Applicative强制执行Functor约束Monad的定义(以及理想情况下的定义要求其实例是Applicatives,因为如果它不是,就不要让它成为MonadApplicative)。
换句话说,上面的代码让我觉得没有办法为 编写Functor实例IO,如果IO首先不是 a Monad。
现在想想,也许这就像说它IO是作为一个成熟的Monad.
但我很困惑,所以我在这里寻求帮助。
Jon*_*rdy 11
具有 实例的类型Monad意味着它必须具有Functor(和Applicative)的定义,但这并不意味着Functor必须“首先”定义该实例,只是两个实例都必须存在。只要方法实现不是循环定义的,就没有问题。
事实上,这通常是有意义的实施Monad为第一类,然后定义Applicative并Functor来讲机械Monad操作,因为Monad更强大,所以其他情况下都只是限制了的Monad实例:
-- These work for any T with a Monad instance.
instance Functor T where
fmap f x = do
x' <- x
return (f x')
instance Applicative T where
pure = return
f <*> x = do
f' <- f
x' <- x
return (f' x')
Run Code Online (Sandbox Code Playgroud)
这正是因为“aMonad是'比'an 多的东西Applicative,而后者又是'比'a 多的东西Functor”。
还值得注意的是,最初,Monad和Functor类是无关的,而Applicative类(后来添加)也是如此。有用于每个,如单独的等同的功能fmap,liftA和liftM; pure和return; (<*>)和ap; traverse和mapM。按照惯例,您会编写一个Monad实例并据此实现其他类。这些单独的定义仍然存在,但现在是多余的:由于“Applicative-Monad Proposal”创建Applicative了Monad, 和Functorof的超类Applicative,您始终可以使用 egpure代替return或traverse代替mapM,因为它们是相同的功能,但在更多的上下文中工作。所以还有一些历史背景,说明为什么可能对一个类型的这些实例有单独的定义。
正如@dfeuer 指出的那样,有些数据结构mapM( mapM_, forM, forM_) 比traverse(resp. traverse_, for, for_)更有效,例如Data.Vector类型。在向量的特定情况下,我相信这是因为该库可以利用 monadic 测序作为优化,以实现更多的流媒体和结果分配。但它们是等价的,因为traverse应该总是产生相同的结果。
| 归档时间: |
|
| 查看次数: |
206 次 |
| 最近记录: |