"有效"究竟是什么意思

Mar*_*urg 29 monads haskell side-effects applicative

一次又一次,我读了长期effectful,但我还是无法给予的是什么意思的明确定义.我认为正确的上下文是effectful 计算,但我也看到了长期effectful )

我曾经认为有效的手段有副作用.但在Haskell中没有副作用(除了某种程度上IO).整个地方仍然有效的计算.

然后我读到monad用于创建有效的计算.我可以在StateMonad 的背景下理解这一点.但我没有看到Maybemonad中有任何副作用.一般来说,在我看来,Monads包含一个类似函数的东西更容易看到产生副作用比Monads只包装一个值.

谈到Applicative仿函数,我更加迷失.我总是看到applicative functor作为一个map带有多个参数的函数的方法.我在这里看不到任何副作用.或者是有之间的差异effectful用的效果

Pet*_*lák 22

副作用是与其环境(除了它的计算结果值)可观察到的相互作用.在Haskell中,我们努力避免具有这种副作用的函数.这甚至适用于IO动作:当IO评估动作时,不执行副作用,仅当在其中IO执行值中规定的动作时才执行它们main.

然而,这都涉及到组成计算,如应用性函子和单子抽象工作时,它的方便与实际值和"休息",这我们常说的"效果"之间的区别有点.特别是,如果我们有一个类型f一种 * -> *,然后在f aa部分是"价值"和"保持"无论是"效果".

我故意引用这些术语,因为没有确切的定义(据我所知),它只是一个口语定义.在某些情况下,根本没有值或多个值.例如,Maybe"效果"是可能没有值(并且计算被中止),因为[]"效果"是存在多个(或零)值.对于更复杂的类型,这种区别可能更加困难.

"效果"和"价值"之间的区别并不真正取决于抽象.Functor,ApplicativeMonad给我们工具我们可以用它们做什么(Functor允许修改内部Applicative的值,s允许组合效果和Monads允许效果取决于以前的值).但是在Monads 的上下文中,创建一个关于正在发生的事情的心理图像要容易一些,因为monadic动作可以"看到"前一个计算的结果值,正如

(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

operator:第二个函数接收一个类型的值a,所以我们可以想象"先前的计算有一些影响,现在有它的结果值,我们可以用它做什么".

  • @MartinDrautzburg正​​如我所写,"效果"和"值"之间的区别是由实际数据类型给出的,而不是我们用来操纵它的抽象.例如,对于"可能","效果"始终是计算可以中止,无论我们是否使用Applicative或Monad(或其他)接口.如果你在`Maybe`中写`f <$> a**b <*> c`,`a`,`b`或`c`中的任何一个都可以用`Nothing`中止计算,这就是它的"影响".Applicative接口允许组合效果(对于'Maybe`,它意味着在第一个'Nothing`上中止),但是不允许效果依赖于先前的值. (4认同)
  • 你能详细说明申请人的"效果"吗?毕竟有一篇论文"应用程序编程与效果",我从来没有完全理解标题(我相信我理解应用程序) (2认同)

dup*_*ode 12

为了支持PetrPudlák的回答,这里有一个论点,涉及在那里支持的更广泛的"效果"概念的起源.

短语"有效编程"出现在McBride和Patterson的" 应用程序编程与效果 "的摘要中,该文章介绍了应用函子:

在本文中,我们介绍Applicative了仿函数 - 一种有效编程的应用风格的抽象表征,比Monads 弱,因此更广泛.

"效果"和"有效"出现在该论文的其他一些段落中; 这些事件被认为是不起眼的,不需要明确澄清.例如,这个评论是在提出定义之后做出的Applicative(第3页):

在每个例子中,都有一个类型构造函数f,它嵌入了通常的值概念,但支持它自己特有的赋予通常应用语言意义的方式[...]我们相应地介绍了Applicative类:

[哈斯克尔的定义Applicative]

这个类概括了SK [即在/函数实例中显示的S和K组合子 ]从一个环境线程化到一般的线程化.ReaderApplicative

从这些引用中,我们可以推断出,在这种情况下:

  • 效果是Applicative"一般"线程的东西.

  • 效果与给定Applicative实例的类型构造函数相关联.

  • Monad 也涉及效果.

在这些线索之后,我们可以追溯到"效应"的这种用法,至少回到了Wadler关于monad的论文.例如,以下是Monads第6页的函数式编程引用:

通常,类型a→b的函数由类型a→M b的函数代替.这可以被理解为接受类型的参数的函数一个 ,并返回型的结果b,与由捕获的可能的附加效果 中号.这种效果可能是对状态,生成输出,引发异常或对你有什么影响.

从同一篇论文,第21页:

如果monads封装效果并且列表形成monad,那么列表是否对应于某些效果?确实他们这样做,他们所对应的效果就是选择.可以将类型[a]的计算视为提供值的选择,对于列表的每个元素一个.类型a→b的函数的monadic等价物是类型a→[b]的函数.

这里的"对应一些效果"转换是关键.它与摘要中更为直接的主张有关:

Monads为模拟其他语言中的效果提供了一个方便的框架,例如全局状态,异常处理,输出或非确定性.

可以用monad来表达那些在"其他语言"中通常被编码为副作用的东西 - 就像PetrPudlák在其答案中所说的那样,"与[函数]的可观察的交互作用"环境(除了计算其结果值)".通过转喻,这很容易导致"效果"获得第二个含义,比"副作用"更广泛 - 即,通过作为Monad实例的类型构造函数引入的任何内容.随着时间的推移,这个含义被进一步推广到涵盖其他仿函数类Applicative,如McBride和Patterson的作品中所见.

总之,我认为"效果"在Haskell的说法中有两个合理的含义:

  • "文字"或"绝对"的:效果是副作用; 和

  • "广义"或"相对"的:效果是一种函数上下文.

有时,当每个相关方隐含地假设"效果"的不同含义时,就会发生对术语的可避免的分歧.另一个可能的争论点涉及在Functor单独处理时是否合法地谈论效果,而不是像(Applicative或)这样的子类Monad(我认为可以这样做,与PetrPudlák的答案一致,为什么应用仿函数有副作用) ,但算人不能?).


Mat*_*hid 6

在我看来,“副作用”是指正常功能无法做到的任何事情。换句话说,除了返回值之外的任何东西。

考虑以下代码块:

let
  y = foo x
  z = bar y
in foobar z
Run Code Online (Sandbox Code Playgroud)

这会调用foo、然后调用bar、然后调用foobar三个普通函数。很简单,对吧?现在考虑一下:

do
  y <- foo x
  z <- bar y
  foobar z
Run Code Online (Sandbox Code Playgroud)

这也调用了三个函数,但它也在(>>=)每对线之间无形地调用。这意味着会发生一些奇怪的事情,具体取决于函数运行的 monad 类型。

  • 如果这是恒等单子,就不会发生什么特别的事情。Monadic 版本与纯版本执行完全相同的操作。没有副作用。

  • 如果每个函数都返回 -something Maybe,那么如果(比如说)bar返回Nothing,则整个代码块将中止。普通函数无法做到这一点。(即在纯版本中,没有办法阻止foobar被调用。)所以这个版本做了一些纯版本做不到的事情。每个函数都可以返回一个值或中止该块。这是一个副作用。

  • 如果每个函数返回一个列表,则代码将针对所有可能的结果组合执行。同样,在纯版本中,无法使任何函数使用不同的参数多次执行。所以这是一个副作用。

  • 如果每个函数都在状态 monad 中运行,那么(例如)除了您可以看到通过 传递的值之外,还foo可以直接向 发送一些数据。同样,你不能用纯函数来做到这一点,所以这是一个副作用。foobarbar

  • IOmonad 中,你会产生各种有趣的效果。你可以将文件保存到磁盘(文件基本上是一个巨大的全局变量),你甚至可以影响其他计算机上运行的代码(我们称之为网络I/O)。

  • monadST是 monad 的简化版本IO。它允许可变状态,但自包含计算不能互相影响。

  • monadSTM允许多个线程相互通信,并可能导致代码执行多次,并且......好吧,您无法使用普通函数执行任何此操作。

  • 延续单子可以让你打破人们的想法!可以说,纯函数是可能的......


归档时间:

查看次数:

2035 次

最近记录:

7 年,3 月 前