Type inference with the Eff monad can be a bit tricky to get right if we want to avoid type annotations. Here are some tips to help you.

Some effects use 2 type variables, like `Reader`

or `Writer`

. If you want to use those effects in an effect stack you need to make sure you have the following `scalac`

option:

`scalacOptions += "-Ypartial-unification"`

When creating effects you can always “require” a stack containing the right effects with the `MemberIn`

typeclass:

```
import org.atnos.eff._
import org.atnos.eff.all._
type StateInt[A] = State[Int, A]
type WriterString[A] = Writer[String, A]
// for creating state effects
def putAndTell[R](i: Int)(implicit s: StateInt |= R, w: WriterString |= R): Eff[R, Int] =
for {
// no type annotations needed!
_ <- put(i)
_ <- tell("stored " + i)
} yield i
```

You can even use context bounds to make the declaration of `putAndTell`

more concise:

```
import org.atnos.eff.all._
type _stateInt[R] = State[Int, ?] |= R
type _writerString[R] = Writer[String, ?] |= R
def putAndTell[R :_stateInt :_writerString](i: Int): Eff[R, Int] =
for {
_ <- put(i)
_ <- tell("stored " + i)
} yield i
```

`Member`

typeclassesThere are 3 different ways to declare that an effect is part of an effect stack with 3 typeclasses:

Typeclass | Alias | Meaning | When to use it |
---|---|---|---|

`MemberIn[M, R]` |
`M |= R` |
“`M` is part of `R` ” |
to create `M` effects in `R` |

`MemberInOut[M, R]` |
`M /= R` |
“`M` is part of `R` and can be extracted from it” |
to intercept the effect `M` (see `Interpreter.scala` ) and transform it while staying in the same stack. For example to `handleError` for an Error effect |

`Member[M, R]` |
`M <= R` |
“`M` is part of `R` , can be extracted from it, and the resulting stack is `m.Out` ” |
to interpret the effect in terms of special values or other effects and remove the effect from the stack |