[英]What are applicative effects?
What is the meaning of the concept of effect in effectful applicative programming ?有效的应用程序编程中效果的概念是什么意思?
For example, which parts of expressions below are the effects ?例如,下面表达式的哪些部分是效果?
[(+1)] <*> [2,3]
Just (+1) <*> Nothing
In the FP world, an effect is any type constructor such as Maybe
, []
, IO
, etc. Effects are not to be confused with side-effects.在 FP 世界中,效果是任何类型的构造函数,例如Maybe
、 []
、 IO
等。不要将效果与副作用混淆。 Intuitively, an effect is an additional property of the value you're computing.直观地说,效果是您正在计算的值的附加属性。 Maybe Int
means that your program calculates an Int
with a failure effect, or [Int]
means that your program calculates an Int
but with a non-deterministic effect (a non-deterministic result is here modeled as a list of possible results). Maybe Int
意味着您的程序计算了一个具有失败影响的Int
,或者[Int]
意味着您的程序计算了一个Int
但具有非确定性影响(非确定性结果在这里建模为可能结果的列表)。
Going from here, we have the terms applicative effects and monadic effects , which mean that the said effects have Applicative
and Monad
instances.从这里开始,我们有术语applicative effects和monadic effects ,这意味着所述效果具有Applicative
和Monad
实例。
I can't find any authoritative information for this, it's just what I have gleaned in my experience.我找不到任何权威信息,这只是我在我的经验中收集到的。
Much confusion was caused by the unfortunate choice of names, as is quite common in Haskell (think " return
", much better named " emit
").不幸的名字选择引起了很多混乱,这在 Haskell 中很常见(想想“ return
”,更好地命名为“ emit
”)。
pure x
is not pure, it is x
that is pure, pure
is just inject . pure x
不纯, pure
x
是纯的, pure
只是注入。 It was envisioned to be used in pure f <*> a <*> b <*> ...
pattern, letting us effectfully apply a pure function f
.它被设想用于pure f <*> a <*> b <*> ...
模式,让我们有效地应用纯函数f
。 (1) (1)
[]
applicative (2) lets us "non-deterministically" apply ( <*>
, not $
) a non-deterministic value (not two values , in your example) to a non-deterministic function; []
应用性(2)让我们“非确定性”应用( <*>
而不是$
)非确定性值(而不是两个值,在你的例子),以非确定性函数; the non-determinism is the effect.非确定性就是效果。 (3) (3)
In list applicative, [(+1), (+2)]
is a non-deterministic function that might increment a value by 1, and also might increment it by 2. [3,4,5]
is a non-deterministic value whose possible values are listed.在列表应用中, [(+1), (+2)]
是一个非确定性函数,它可能将一个值增加 1,也可能将它增加 2。 [3,4,5]
是一个非确定性值列出了其可能的值。 Just as we apply normal entities (+1)
and 3
normally, as (+1) $ 3
, so can we apply non-deterministic values non-deterministically , as [(+1)] <*> [3]
or [(+1),(+2)] <*> [3,4,5]
.正如我们应用正常的实体(+1)
和3
通常,如(+1) $ 3
,所以可以我们应用非确定性值的非确定性,如[(+1)] <*> [3]
或[(+1),(+2)] <*> [3,4,5]
。
And with Maybe
the possibility of failure is the effect.与Maybe
失败的可能性是效果。
(1) as the paper says, in Introduction: "we collect the values of some effectful computations, which we then use as the arguments to a pure function (:)
" (1)正如论文在介绍中所说: “我们收集一些有效计算的值,然后将其用作纯函数的参数(:)
”
(2) []
by itself is not an applicative, ([], pure :: a -> [a], (<*>) :: [a -> b] -> [a] -> [b])
is an applicative, given some (lawful) implementations of pure
and (<*>)
. (2) []
本身不是一个应用, ([], pure :: a -> [a], (<*>) :: [a -> b] -> [a] -> [b])
考虑到pure
和(<*>)
一些(合法)实现,是一种应用。
(3) x
is pure (as in, "Haskell is pure"); (3) x
是纯的(如“Haskell 是纯的”); pure x
stands for an effectful computation producing x
without actually having any additional effect. pure x
代表有效计算产生x
而实际上没有任何附加效果。 "without an effect" refers to the law of pure x *> u == u
ie pure x
doesn't add any effect into the combined computation on top of u
's contribution. “没有影响”指的是pure x *> u == u
定律,即pure x
不会在u
贡献之上的组合计算中添加任何影响。 But the possibility of effect is there.但效果的可能性是存在的。
pure 7 :: IO Int
is certainly not the pure (as in, "Haskell is pure") value 7
, it is the pure value 7
in the effectful context ( IO
). pure 7 :: IO Int
当然不是纯(如“Haskell 是纯的”)值7
,它是有效上下文( IO
)中的纯值7
。 Even if it does no effectful action in that context, it's still in that context ( IO
).即使它在那个上下文中没有采取有效的动作,它仍然在那个上下文中( IO
)。
on the other hand, and unrelated to the purpose of pure
, of course any Haskell value is pure and referentially transparent.另一方面,与pure
的目的无关,当然任何Haskell 值都是纯的并且引用透明。 getLine
is a pure, referentially transparent Haskell value . getLine
是一个纯粹的、引用透明的 Haskell值。 It stands for an effectful I/O computation , getting an input line from a user and producing it as the result to be used by the next I/O computation.它代表有效的 I/O计算,从用户那里获取输入行并将其作为结果供下一个 I/O 计算使用。
print 7
is a pure referentially transparent Haskell value. print 7
是一个纯粹的引用透明 Haskell 值。 that's not a kind of "pure" that is meant here.这不是这里所说的一种“纯”。 [1,2]
is a pure value, but seen from another angle it's a nondeterministic value with two possible pure values 1
and 2
. [1,2]
是一个纯值,但从另一个角度来看,它是一个不确定值,具有两个可能的纯值1
和2
。 Same for [1]
. [1]
。 It can still be interpreted as a nondeterministic value with one possible pure value, 1
.它仍然可以解释为具有一个可能的纯值1
的不确定值。
[1,2] *> [10,20]
= [10,20,10,20]
; [1,2] *> [10,20]
= [10,20,10,20]
; [1] *> [10,20]
= [10,20]
. [1] *> [10,20]
= [10,20]
。 So unlike [1,2]
, [1]
doesn't add any nondeterminism into the nondeterministic computation described by [10,20]
.因此,与[1,2]
不同, [1]
不会在[10,20]
描述的非确定性计算中添加任何不确定性。 But it's still a nondeterministic value, it can participate in *>
.但它仍然是一个不确定的值,它可以参与*>
。 1
can't. 1
不能。 ( [1]
is of course the same as pure 1
). ( [1]
当然与pure 1
相同)。
We know a type by what kind of interactions it can participate in.我们通过它可以参与的交互类型来了解类型。
Or, as the user @bob puts it ( in the comments ), " pure x
puts a pure x
into an effectful context without actually performing [any] effect".或者,正如用户@bob所说的( 在评论中),“ pure x
将纯x
置于有效上下文中,而不实际执行 [任何] 效果”。
See also:也可以看看:
We could say that an effect of type fa
is anything that can't be written as pure x
where x :: a
.我们可以说fa
类型的效果是任何不能写成pure x
其中x :: a
。
In the []
applicative, pure x = [x]
, so [(+1)] = pure (+1)
probably shouldn't be considered an effect.在[]
应用中, pure x = [x]
,因此[(+1)] = pure (+1)
可能不应被视为效果。 Similarly in the Maybe
applicative, pure = Just
, so Just (+1)
is not an effect.同样,在Maybe
应用中, pure = Just
,所以Just (+1)
不是效果。
That leaves [2,3]
and Nothing
as the effects in your respective examples.这将[2,3]
和Nothing
作为您各自示例中的效果。 This makes intuitive sense from the perspective that []
denotes nondeterministic computations: [2,3]
nondeterministically chooses between 2 and 3;从[]
表示非确定性计算的角度来看,这具有直观意义: [2,3]
在 2 和 3 之间非确定性地选择; and the perspective that Maybe
denotes failing computations: Nothing
fails the computation.以及Maybe
表示计算失败的观点: Nothing
失败计算。
The definition I used that an effect (perhaps "side-effect" would be a better word) is something that can't be written as pure x
is just a swing at making your question precise, and does not represent any sort of consensus or standard definition.我使用的定义是效果(也许“副作用”会是一个更好的词)不能写成pure x
只是使您的问题变得精确的一种摆动,并不代表任何形式的共识或标准定义。 Will Ness's answer gives a different perspective, that pure
generates an effectful computation from a pure value, which has a nice mathematical ring to it -- ie this definition would probably be easier to use in precise settings. Will Ness 的回答给出了一个不同的观点, pure
从一个纯值生成一个有效的计算,它有一个很好的数学环 - 即这个定义可能更容易在精确设置中使用。
Effectful applicative programming can be thought of as taking regular non-effectful computations and adding effects to them.有效的应用程序编程可以被认为是进行常规的无效计算并为其添加效果。 These are implemented as Applicative
instances.这些被实现为Applicative
实例。 So while Int
is a regular value, A Int
is an Int
with some effect A
, and A
is an instance of Applicative
.因此,虽然Int
是常规值,但A Int
是具有某种效果的Int
A
,而A
是Applicative
的实例。
Consider this expression:考虑这个表达式:
x + y :: Int
This expression is not effectful;这个表达是无效的; it only deals with regular, plain values, so to speak.可以这么说,它只处理常规的、简单的值。 But we can also have effectful addition .但是我们也可以有有效的加法。
One effect is failure ;一种影响是失败; the computation may fail or succeed.计算可能失败或成功。 If it fails, then the computation is stopped.如果失败,则停止计算。 This is simply the Maybe
type.这只是Maybe
类型。
Just (+1) <*> Nothing :: Maybe Int
In addition with regular values, you just add the numbers together.除了常规值之外,您只需将数字相加即可。 But now, we have addition that might fail .但是现在,我们有可能会失败的加法。 So we have to add the numbers together provided that the computation has not failed .所以我们必须把这些数字加在一起,前提是计算没有失败。 We see in this expression that the computation will fail, since the second operand is Nothing
.我们在这个表达式中看到计算将失败,因为第二个操作数是Nothing
。
If your computations can fail for more than simply one reason, you might want to have error messages that report the kind of failure that happened.如果您的计算失败的原因不止一个,您可能需要错误消息来报告所发生的失败类型。 Then you may use an error effect, which might be represented as something like Either String
( String
is the type of the error message).然后你可以使用一个错误效果,它可能表示为类似Either String
( String
是错误消息的类型)。 The implementation of this Applicative
behaves similarly to the Maybe
Applicative
.此Applicative
的实现与Maybe
Applicative
行为类似。
Another example of an effect is parsing.效果的另一个例子是解析。 Parsing can be implemented by just using constructors and making them effectful.只需使用构造函数并使其有效就可以实现解析。 Say you want to implement a simple arithmetic language with addition and multiplication.假设您想实现一种带有加法和乘法的简单算术语言。 This could be your abstract syntax tree (AST):这可能是您的抽象语法树 (AST):
data Exp = Num Int | Var String
data AST = Add Exp Exp | Multiply Exp Exp
You build up the AST by simply using these constructors.您只需使用这些构造函数即可构建 AST。 But the problem is that you also need to actually parse the text, so what about the act of parsing?但问题是你还需要真正解析文本,那么解析的行为呢? What about keeping track of how much of the text you have consumed?如何跟踪您已阅读了多少文本? What if the parsing fails , because the text did not conform to your grammar?如果解析失败,因为文本不符合您的语法怎么办? Well, in libraries like Parsec
, that is the parsing effect .好吧,在像Parsec
这样的库中,这就是解析效果。 You use some Parse
data type (that is an instance of Applicative
) and lift the constructors into the effectful Parse AST
world.您使用一些Parse
数据类型(即Applicative
的实例)并将构造函数提升到有效的Parse AST
世界中。 Now, you can construct the AST while actually parsing the text, because the parsing is an effect added to the construction of the AST.现在,您可以在实际解析文本的同时构建 AST,因为解析是添加到 AST 构建中的效果。
Notice that the Parse
type was more complicated than both the Maybe
and Either String
instances;请注意, Parse
类型比Maybe
和Either String
实例都复杂; the parser has the effects of keeping track of state like how much of the input text that has been consumed, and a failed parse, which would yield an error message.解析器具有跟踪状态的作用,例如已经消耗了多少输入文本,以及解析失败,这会产生错误消息。 Applicative
effects can be composed together like this. Applicative
效果可以像这样组合在一起。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.