gor*_*sky 10 monads haskell applicative
在"为了好大学而学习你的哈斯克尔!" 作者声称Applicative IO实例是这样实现的:
instance Applicative IO where
pure = return
a <*> b = do
f <- a
x <- b
return (f x)
Run Code Online (Sandbox Code Playgroud)
我可能是错的,但似乎都return和do特异性结构(一些加糖的结合(>>=))来自Monad IO.假设这是正确的,我的实际问题是:
为什么Applicative IO实现依赖于Monad IO函数/组合器?
是不是没有Applicative 那么强大的概念Monad?
编辑(一些澄清):
这种实现违背了我的直觉,因为根据Typeclassopedia的文章,在给定类型Applicative 之前需要它Monad(或者它应该在理论上).
C. *_*ann 12
(...)根据Typeclassopedia的文章,它必须在给定类型之前被应用为Monad(或者它应该在理论上).
是的,你的括号旁边就是这里的问题.理论上,任何一个也Monad 应该是一个Applicative,但实际上并不是必需的,因为历史原因(即,因为Monad已经存在更长时间).这也不是唯一的特点Monad.
考虑相关类型类的实际定义,取自baseHackage上的软件包源代码.
这是Applicative:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Run Code Online (Sandbox Code Playgroud)
......我们可以观察以下内容:
Functor.同时,这里是Monad:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
Run Code Online (Sandbox Code Playgroud)
......我们可以观察以下内容:
Applicative,而且Functor两者都在逻辑上暗示,Monad但没有明确要求.return和更加数学上自然的定义join.fail根本不适合的.通常,Monad类型类与它所基于的数学概念的不同之处可以追溯到它作为编程抽象的历史.有些像它所共享的函数应用程序偏差一样Applicative,是功能语言中存在的反映; 其他人,比如fail或缺乏适当的阶级背景,是历史事故最重要的事情.
这一切归结为具有一个Monad暗示实例的实例Applicative,而实例又暗示了一个实例Functor.类上下文只是明确地将其形式化; 无论如何都是如此.因为它的立场,给定一个Monad实例,都Functor和Applicative在一个完全通用的方式来定义.Applicative它是"不那么强大",而不是Monad完全相同的意义,它更通用:如果你复制+粘贴通用实例,Monad则会自动执行Applicative,但是存在Applicative无法定义为的实例Monad.
一个类上下文,就像Functor f => Applicative f说两件事:后者暗示前者,并且必须存在一个定义来实现这个含义.在许多情况下,定义后者无论如何都隐含地定义了前者,但编译器通常不能推断出这种情况,因此需要明确地写出两个实例.同样的事情可以用Eq和观察Ord- 后者显然暗示前者,但你仍然需要定义一个Eq实例来定义一个实例Ord.
IOHaskell中的类型是抽象的,因此如果要实现通用Applicative,IO则必须使用IO支持的操作.既然你可以Applicative在Monad操作方面实现,这似乎是一个不错的选择.你能想到另一种实现它的方法吗?
是的,Applicative在某种程度上不如强大Monad.
不是应用比Monad 更强大的概念吗?
是的,因此无论什么时候有Monad你,你都可以随时做到Applicative.您可以替换IO示例中的任何其他monad,它将是一个有效的Applicative实例.
作为类比,虽然彩色打印机可能被认为比灰度打印机更强大,但您仍然可以使用彩色打印机打印灰度图像.
当然,也可以将一个Monad实例基于Applicative和设置return = pure,但是你无法>>=一般地定义.这是Monad更有力的手段.