Effect Typing for Scala
A short introduction to the Effects Plugin for Scala
LAMP/LARA Seminar Talk, Lukas Rytz, May 2013
(use arrow keys to navigate)
## Big Picture
* A [compiler plugin](https://github.com/lrytz/efftp) for stock Scala 2.10.1
* Entirely based on annotations, no changes to Scala's syntax
* Effect-annotated code compiles without the plugin (it's a [pluggable type system](http://bracha.org/pluggableTypesPosition.pdf))
* Currently supports I/O effects, checked exceptions and purity (state effects)
* Documentation on the [Github Wiki](https://github.com/lrytz/efftp/wiki)
Just WorksTM in Eclipse
## Syntax
* Effects are annotated on return types of methods
```scala
def inc(i: Int): Int @pure = i + 1
```
* Effects are inferred if the return type is inferred
```scala
def inc(i: Int) = i + 1 // effect is inferred
```
* Methods with a return type, but without effect annotations have an unknown effect
```scala
def inc(I: Int): Int = i + 1 // impure!
```
## Multiple Effect Domains
* Effect annotations are simply put next to each other
```scala
def div(a: Int, b: Int): Int @noIo @mod() @throws[DivByZero] = ...
```
* By default, non-annotated domains are impure
* The `@pure` annotation marks a method pure across all effect domains
```scala
def div(a: Int, b: Int): Int @pure @throws[DivByZero] = ...
```
## Effect Polymorphism
* The effect of a higher-order method usually depends on the effect of its argument:
```scala
def h(f: Int => Int): Int @pure(f) = {
f(1)
}
```
* The _relative effect annotation_ `@pure(f)` marks `h` as pure, up to the effect of `f` (more precisely: `f.apply`)
* Relative effects are not tied to function types
```scala
def sayHi(g: Greeter, name: String): Unit @pure(g.greet(%)) = {
g.greet(name)
}
```
## Purity
* A method is pure, annotated `@mod()` (or `@pure`) if it does not modify any state that existed before its execution
* The annotation `@mod(c)` allows modifying fields of parameter `c`
```scala
def inc(c: Counter): Unit @pure @mod(c) = {
c.value = c.value + 1
}
```
* Modifying freshly allocated state within a method is not observable, therefore allowed:
```scala
def counterFrom(i: Int): Counter @pure = {
val c = new Counter
for (_ ← 0 until i) inc(c)
c
}
```
## Freshness / Returned Locality
* The `@loc` annotation denotes the locality of the object returned by a method
```scala
def inc(c: Counter): Counter @mod(c) @loc(c) = {
c.inc()
c
}
```
* Constructors and factory methods a new object on every invocation, annotated `@loc()`
```scala
def counterFromTwo: Counter @pure @loc() = {
val c = new Counter
c.inc().inc()
}
```