Haskell绑定运算符如何从monad中提取值?
如果这个问题听起来很愚蠢,请原谅我,我仍然是学习 Haskell 的初学者。
给定绑定运算符函数签名:
(>>=) :: m a -> (a -> m b) -> m b
我的问题是,如何从“m a”中提取“a”值以便函数(a -> m b)可以触发?haskell 是否在内部对此进行了抽象?
回答
这是由编写Monad特定类型实例的人实现的。
例如,如果我们看instance的Monad了Maybe,我们看到的[来源]:
-- | @since 2.01 instance Monad Maybe where (Just x) >>= k = k x Nothing >>= _ = Nothing (>>) = (*>)
而对于列表 [src] 的一个实例,我们看到:
-- See Note: [List comprehensions and inlining] -- | @since 2.01 instance Monad [] where {-# INLINE (>>=) #-} xs >>= f = [y | x <- xs, y <- f x] {-# INLINE (>>) #-} (>>) = (*>)
如果您因此将某些东西作为Monad类型类的实例,您将需要为该(>>=)函数提供一个实现。
- @AndrewTang:还值得注意的是,`ma` 类型的 monadic 值根本不一定“包含”一个 `a`,它更像是一个“`a` 的来源”。一些实例(如`[]`、`Maybe`、`Either`、`Identity`)是类容器的;但是其他的(比如`IO`、`Reader`、`Cont`、`Async`、`Parsec`)更像是*actions*。这就是为什么初学者常问的问题“如何从 `IO String` 中取出 `String`?” 不太合理,因为那里没有`String`:`IO String` 更像是一个*程序*,它可以返回一个`String`。