支持
Petr Pudlák的回答,以下是关于那里所支持的更广泛的“效果”概念起源的论点。
短语“effectful programming”出现在McBride和Patterson的
Applicative Programming with Effects摘要中,这篇论文介绍了applicative functors:
“在本文中,我们介绍了
Applicative
functors——一种弱于
Monad
但更为普遍的effectful programming应用风格的抽象特征。”
“Effect”和“effectful”在该论文的其他几个段落中也出现过;这些发生被认为不足以需要明确的澄清。例如,在
Applicative
的定义呈现之后(第3页)就做出了这样的评论:
在每个示例中,都有一个类型构造函数
f
,它嵌入了通常的值概念,但支持其自己独特的方式来赋予通常应用语言意义[...]我们相应地引入了
Applicative
类:
[一个
Applicative
的Haskell定义]
该类将
S和
K(即
S和K组合子,它们出现在
Reader
/函数
Applicative
实例中)从线程化环境推广到线程化一般效果。
从这些引用中,我们可以推断,在这个上下文中:
- 效果是
Applicative
“一般情况下”线程化的东西。
- 效果与获得
Applicative
实例的类型构造函数相关联。
-
Monad
也处理效果。
跟随这些线索,我们可以追溯回到至少
Wadler的关于单子的论文。例如,以下是《函数式编程的单子》第6页的引用:
一般情况下,类型为a → b的函数将被类型为a → M b的函数替换。这可以理解为一个函数接受类型为a的参数并返回类型为b的结果,其中可能包含由M捕获的附加效果。该效果可以是状态操作、输出生成、异常引发等。从同一篇论文的第21页可以得知,如果单子封装了效果并且列表形成了一个单子,那么列表对应于某种效果。实际上,它们确实如此,并且它们对应的效果是选择。可以将类型为[a]的计算视为提供值的选择,每个元素都有一个值。类型为a → b的单子等效于类型为a → [b]的函数。这里的“对应于某种效果”是关键词语。它与摘要中更直接的声明相呼应:“单子提供了一个方便的框架,用于模拟其他语言中发现的效果,例如全局状态、异常处理、输出或非确定性。”
这里的意思是,单子可以用来表达在“其他语言”中通常编码为副作用的事物——即,正如Petr Pudlák在这里所说,“与[函数]环境的可观察交互(除计算其结果值外)”。通过转喻,这很容易导致“效果”获得第二个更广泛的意义,比“副作用”更广泛,即通过类型构造引入的任何东西,该类型构造是一个
Monad
实例。随着时间的推移,这个意义进一步概括为涵盖其他函数类别,如McBride和Patterson的工作中所看到的
Applicative
。
总之,在Haskell术语中,“effect”有两个合理的含义:
一个“字面”或“绝对”的含义:效果是副作用;以及
一个“广义”或“相对”的含义:效果是函子上下文。
有时候,当每个相关方暗示不同的“效果”含义时,可能会发生可避免的术语分歧。另一个可能引起争议的地方是,在处理Functor
而不是子类(如Applicative
或Monad
)时,是否可以合法地谈论效果(我认为可以这样做,并与Petr Pudlák对为什么适用的函子可以具有副作用,但函子不能?达成一致)。
State s a
视为类似于命令式子程序的函数很常见。它可以读/写状态s
并带有副作用,最后生成一个a
。即使它是纯的,有时候假装它不是也是很方便的。关于主题,我认为“effectful”和“with effects”的意思是相同的,即使它们有时被广泛地应用于任何Monad / Applicative包装的值,即使这些值并没有建模副作用。 - chiliftA2
将函数“隐藏”,包装的效果被合并成一个组合的“有副作用”的包装值。而且,pure id <*> x = x
即pure
创建了一个“最小”的包装/效果,其存在于链中不会改变任何东西。 - Will Ness