5 ms·
Rather than talking in terms of “purity”, it's better to talk in terms of “effects”. Raising an exception is an effect. Returning different results when passed
by catnaroek 10y ago
Rather than talking in terms of “purity”, it's better to talk in terms of “effects”. Raising an exception is an effect. Returning different results when passed the same arguments twice is an effect. I/O is an effect. Looping forever (also known as “divergence” in some circles) is an effect. What you call “purity” is just the absence of effects.
From the point of view of programming language semantics, what all effects have in common is that they reduce the extent to which equational reasoning is applicable to our programs. For example,
f(x) == f(x)
doesn't always hold if `f` is a non-deterministic procedure, and
function foo_bar() {
var x = foo();
var y = bar();
return (x, y);
}
isn't the same as
function bar_foo() {
var y = bar();
var x = foo();
return (x, y);
}
if `foo` and `bar` have effects that don't commute.
---
Higher-order functions also give us an interesting possibility: effect polymorphism. Let's consider the humble `map` function, operating on lists:
map _ [] = []
map f (x :: xs) = f x :: map f xs
Intuitively, it's clear that `map f` is an effectful procedure if and only if `f` is an effectful procedure. This notion can be formalized by giving `map` the following type signature:
forall (a b : Type) (f : Effect). (a -f-> b) -> (List a -f-> List b)
Where `Foo -Bar-> Qux` means “procedure with argument type Foo, effect Bar, and return type Qux”, and `Foo -> Bar` is sugar for `Foo -Pure-> Bar`.
- chriswarbo 10y agoAlgebraic effects are a way to make well-behaved languages (Haskell, Idris, etc.) more intuitive/generic/terse/etc. to write; I'm not sure how useful they are for reasoning about an arbitrary snippet of JS taken from the wild. One problem stated in the article is we can't even rely on things like variable substitution to be effect-free, due to mechanisms like "valueOf". For example, in your "map" definition, the value of "f" called at the head of the list may differ from the value of "f" passed to the recursive call. With this level of monkey-patching possible, it becomes quite hard to say anything about a piece of code other than "it's return type is Any, it might throw an exception, and it could perform arbitrary effects" :(
- catnaroek 10y ago> I'm not sure how useful they are for reasoning about an arbitrary snippet of JS taken from the wild. Probably not much, indeed. > One problem stated in the article is we can't even rely on things like variable substitution to be effect-free I have no idea how to make sense of this. The presence or absence of effects is an object language notion. Variable substitution is an operation on the syntax of this object language, and syntax necessarily lives in a metalanguage (e.g., the language in which a compiler or interpreter is written). EDIT: Forgot about explicit substitutions, which make substitution an explicit reduction step in the object language. Even then, I don't see how substitution can be effectful by itself. > For example, in your "map" definition, the value of "f" called at the head of the list may differ from the value of "f" passed to the recursive call. At least in a call-by-value language, this is should never the case. Funny things can happen if lexical environments are first-class objects, of course.
- chriswarbo 10y ago> I have no idea how to make sense of this. Maybe I should have used a different phrase. I meant that an expression consisting of a variable (e.g. "x") may be evaluated as if it were a dynamically-dispatched function call (e.g. "x.valueOf()"), so even the most innocent-looking expression may contain hooks to which someone may have attached an effect. Even though JS is call-by-value, implicitly-called methods like "valueOf" allow values in normal form to act like thunks with arbitrary side-effects, which causes a dependence on evaluation order even for such innocent-looking expressions as "x".
- catnaroek 10y agoWow, this is terrible. I already knew I didn't know JavaScript. But I didn't know the extent to which I don't know JavaScript.