haskell - 函数单子真的提供了比函数应用函子更多的东西吗?如果是这样,是什么?
问题描述
对于函数 monad,我发现(<*>)
and (>>=)
/(=<<)
有两种非常相似的类型。特别是,(=<<)
使相似性更加明显:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
(=<<) :: (a -> r -> b) -> (r -> a) -> (r -> b)
因此,就像(<*>)
and (>>=)
/(=<<)
采用二元函数和一元函数,并通过后者约束前者的两个参数之一与另一个参数确定。毕竟,我们知道对于函数 applicative/monad,
f <*> g = \x -> f x (g x)
f =<< g = \x -> f (g x) x
而且它们看起来非常相似(或对称,如果你愿意的话),我不禁想到标题中的问题。
至于 monad 比 applicative functors “更强大”,在LYAH 的For a Few Monads More章节的硬拷贝中,陈述如下:
[…]
join
不能仅通过使用仿函数和应用程序提供的功能来实现。
即join
不能用(<*>)
,pure
和来实现fmap
。
但是我上面提到的函数applicative/mondad 呢?
我知道 ,join === (>>= id)
对于归结为 的函数 monad \f x -> f x x
,即二进制函数通过将后者的一个参数作为前者的两个参数提供而成为一元函数。
我可以用 来表达(<*>)
吗?好吧,实际上我认为我可以:不flip ($) <*> f === join f
正确吗?不是没有/和flip ($) <*> f
的实现吗?join
(>>=)
(=<<)
return
但是,考虑到列表 applicative/monad,我可以join
在不显式使用(=<<)
/(>>=)
和return
(甚至不是(<*>)
,fwiw)的情况下表达join = concat
:所以可能实现join f = flip ($) <*> f
也是一种技巧,并没有真正表明我是依赖Applicative
还是依赖Monad
.
解决方案
当您join
这样实现时,您使用的功能类型知识超出Applicative
了您的范围。这些知识在使用中被编码($)
。那就是“应用程序”运算符,它甚至是函数的核心。您的列表示例也会发生同样的情况:您正在使用concat
,它基于对列表性质的了解。
一般来说,如果您可以使用特定 monad 的知识,您就可以表达任何幂的计算。例如,Maybe
你可以匹配它的构造函数并以这种方式表达任何东西。当 LYAH 说 monad 比 applicative 更强大时,它的意思是“作为抽象”,而不适用于任何特定的 monad。
推荐阅读
- vector - ShaderToy 的 FragCoord.xy 值等
- java - 如何替换作为框架面板之一的 JPanel 内的单个组件
- php - PSALM:Docblock 定义的类或接口不存在
- python - 当数据从mysql导入数据时,双数据通过python pandas转换为float数据
- android - 找不到方法类路径()
- lua - 如何使用带有特殊字符的 gsub
- scala - 给定一个行为的实例,我可以向它应用一条消息来创建一个新的行为吗
- python - 熊猫在列中找到最接近的值
- typescript - 该方法应该返回什么类型?
- java - 在 Spring Boot 的运行时创建一个常量字段