haskell - 应用函子方面的一元序列
问题描述
假设我们有一个单子序列:
doSomething = do
a <- f
b <- g
c <- h
pure (a, b, c)
我们可以使用 applicative functor 轻松地重写它:
doSomething2 = (,,) <$> f <*> g <*> h
但是如果单子序列看起来像这样:
doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)
那里仍然可以使用应用程序吗?如果没有,障碍是什么?(另外在一本书中写到,尽管如此,我们可以将 applicative 和join
一起使用,但我不知道如何使用)。
解决方案
不,这正是 Monad 相比 Applicative 带来的额外力量。可以将类型的单子或应用值f a
视为两部分:“效果”(发生在f
数据结构中的东西)和“值”(发生在 type 的值中的东西a
)。使用 Applicative,效果不可能依赖于值,因为 Applicative 中的函数无法将函数的结果(值)编织回效果中。Monad 中的(>>=)
函数为您提供了这种能力;join
同等强大。
关键是 for 的签名(>>=)
包含一个看起来像这样的函数(a -> m b)
:你可以查看一个纯值( ),然后根据它a
选择一个效果。(m b)
比较
(>>=) :: Monad m => (a -> m b) -> m a -> m b
到
fmap :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
最后两个只接受完全在价值领域运作的功能:(a -> b)
,因此不能根据价值确定结构/效果。
当然,你仍然可以对这个do
符号进行去糖,但是你必须在结果中使用一元操作:
doSomething'' n =
f n >>= (\a ->
g a >>= (\b ->
h b >>= (\c ->
pure (a, b, c))))
推荐阅读
- python - 如果与列表匹配,则删除字符串
- javascript - 为什么我的接收者的类实例方法收不到任何数据?
- r - 在 R 中创建重复向量的替代方法
- chatbot - php json 中 Facebook messanger 聊天机器人响应的新行问题
- javascript - 错误消息:无法绑定到 xxx,因为在调用角度组件时它不是 yyy 的已知属性
- javascript - Croppie 插件不工作。无法在“CanvasRenderingContext2D”上执行“弧”:提供的半径为负
- qt - 为什么我不能使用从 Qt Marketplace 购买的 qt 模块?
- javascript - 从两个数组递归构建 JSON
- shell - 如何将给定文件的行通过管道传输到 shell 命令中?
- ios - Flutter IOS构建中的无效二进制问题