# Cookbook

A collection of examples of how to solve particular problems with Eff

### Partial Interpretation

It’s common to want to use different effects in different parts of a program. Some effects, like error handling or logging, may extend through the whole of our program. However we may want to include additional effects, like state, within one part.

The example below shows how we can do this

• the `incrementNTimes` methods uses an additional `State` effect for its implementation (necessary to call `incrementCounter`)

• the additional `State` effect is added to `R` with the `prepend` method: `Fx.prepend[StateInt, R]`

• `runState` is called within `incrementNTimes` to finally interpret that effect

``````import cats._, data._
import cats.implicits._
import org.atnos.eff._
import org.atnos.eff.all._
import org.atnos.eff.syntax.all._

// Some type definitions for the effects we will use
type EitherString[A] = Either[String, A]
type WriterString[A] = Writer[String, A]
type StateInt[A] = State[Int, A]

type _err[R] = EitherString |= R
type _log[R] = WriterString |= R
type _count[R] = StateInt |= R

/**
* In module 1, some utility methods
*/

// repeat a side-effect n times
def repeatM[M[_]: Monad](n: Int, computation: M[Unit]): M[Unit] =
if (n <= 0) computation
else computation >> repeatM(n - 1, computation)

// check a condition and abort computations with a message if the condition is false
def assert[R: _err](condition: Boolean, msg: String): Eff[R, Unit] =
if (!condition) left(msg) else right(())

// increment a counter and log the new value
def incrementCounter[R: _log: _count]: Eff[R, Unit] = for {
c <- get
c2 = c + 1
_ <- tell(s"counter == \$c2")
_ <- put(c2)
} yield ()

/**
* In module 2 your "business" logic
*/

// increment a value n times (n need to be positive)
def incrementNTimes[R: _err: _log](start: Int, times: Int): Eff[R, Int] = for {
// this call uses the stack R
_ <- assert(times >= 0, s"\$times is negative")

// the call uses the stack R plus an additional StateInt effect which is interpreted right away.
// The other effects remain
result <- repeatM(times, incrementCounter[Fx.prepend[StateInt, R]]).execState(start)
} yield result

/**
* A top-level call
*/

type Stack = Fx.fx2[EitherString, WriterString]

incrementNTimes[Stack](3, 2).runWriter.runEither.run``````

```> Right((6,List(counter == 4, counter == 5, counter == 6)))```