Skip to content

Instantly share code, notes, and snippets.

@msiegenthaler
Last active July 19, 2017 14:31
Show Gist options
  • Save msiegenthaler/1460beb98acfb229f989c2b2746e3c43 to your computer and use it in GitHub Desktop.
Save msiegenthaler/1460beb98acfb229f989c2b2746e3c43 to your computer and use it in GitHub Desktop.
atnos eff: combining effects
package lib.eff
import scala.language.higherKinds
import cats.data.State
import org.atnos.eff.either._
import org.atnos.eff.option._
import org.atnos.eff.state._
import org.atnos.eff.{Eff, MemberIn}
sealed trait Members[R]
object Members {
case class MNil[R]() extends Members[R]
sealed trait MCons[T[_], R] extends Members[R] {
type Tail
val tail: Tail
def memberIn: MemberIn[T, R]
}
type Append[T[_], R, M] = MCons[T, R] { type Tail = M }
type members1[T1[_], R] = Append[T1, R, MNil[R]]
type members2[T1[_], T2[_], R] = Append[T2, R, members1[T1, R]]
type members3[T1[_], T2[_], T3[_], R] = Append[T3, R, members2[T1, T2, R]]
type members4[T1[_], T2[_], T3[_], T4[_], R] = Append[T4, R, members3[T1, T2, T3, R]]
type members5[T1[_], T2[_], T3[_], T4[_], T5[_], R] = Append[T5, R, members4[T1, T2, T3, T4, R]]
object use {
// Extract the members
implicit def select[T[_], R](implicit value: MCons[T, R]): MemberIn[T, R] =
value.memberIn
implicit def recurse[T[_], X[_], R, M](implicit
value: Append[X, R, M],
m: MembersIn[T, R, M]): MemberIn[T, R] = m.memberIn(value.tail)
sealed trait MembersIn[T[_], R, M] {
def memberIn(m: M): MemberIn[T, R]
}
object MembersIn {
def apply[T[_], R, M](implicit membersIn: MembersIn[T, R, M]): MembersIn[T, R, M] =
implicitly
implicit def select[H[_], R, T]: MembersIn[H, R, Append[H, R, T]] = new MembersIn[H, R, Append[H, R, T]] {
def memberIn(m: Append[H, R, T]): MemberIn[H, R] = m.memberIn
}
implicit def recurse[H[_], R, T, U[_]](
implicit
next: MembersIn[U, R, T]
): MembersIn[U, R, Append[H, R, T]] = new MembersIn[U, R, Append[H, R, T]] {
def memberIn(m: Append[H, R, T]): MemberIn[U, R] = next.memberIn(m.tail)
}
}
def memberIn[T[_], R](implicit m: MemberIn[T, R]): MemberIn[T, R] = m
}
// Make from members
object define {
trait Appender[T[_], R] {
def to[M <: Members[R]](to: M): Append[T, R, M]
}
def append[T[_], R](implicit e: MemberIn[T, R]) = new Appender[T, R] {
def to[M <: Members[R]](to: M): Append[T, R, M] = new MCons[T, R] {
type Tail = M
val tail = to
def memberIn: MemberIn[T, R] = e
}
}
implicit def members1[T[_], R](implicit e: MemberIn[T, R]): members1[T, R] =
append[T, R].to(MNil())
implicit def members2[T1[_], T2[_], R](implicit m: members1[T1, R], e: MemberIn[T2, R]): members2[T1, T2, R] =
append[T2, R].to(m)
implicit def members3[T1[_], T2[_], Tl[_], R](implicit m: members2[T1, T2, R], e: MemberIn[Tl, R]): members3[T1, T2, Tl, R] =
append[Tl, R].to(m)
implicit def members4[T1[_], T2[_], T3[_], Tl[_], R](implicit m: members3[T1, T2, T3, R], e: MemberIn[Tl, R]) =
append[Tl, R].to(m)
implicit def members5[T1[_], T2[_], T3[_], T4[_], Tl[_], R](implicit m: members4[T1, T2, T3, T4, R], e: MemberIn[Tl, R]) =
append[Tl, R].to(m)
}
}
object Test3 {
import Members._
def call1[R: _option]: Eff[R, String] = {
import Members.define._
T1.a
}
def call2[R: _option: MemberIn[Either[String, ?], ?]]: Eff[R, String] = {
import Members.define._
T2.a
}
def call3[R: _option: MemberIn[Either[String, ?], ?]: MemberIn[State[String, ?], ?]]: Eff[R, String] = {
import Members.define._
T3.a
}
def call4[R: _option: MemberIn[Either[String, ?], ?]: MemberIn[State[String, ?], ?]]: Eff[R, String] = {
import Members.define._
T4.a
}
object T1 {
import Members.use._
type _effects[R] = members1[Option, R]
def a[R: _effects]: Eff[R, String] =
some("hi")
}
object T2 {
import Members.use._
type _effects[R] = members2[Option, Either[String, ?], R]
def a[R: _effects]: Eff[R, String] =
some("hi")
def b[R: _effects]: Eff[R, String] =
left("No")
def c[R: _effects]: Eff[R, String] =
right[R, String, String]("ok")
}
object T3 {
import Members.use._
type _effects[R] = members3[Option, Either[String, ?], State[String, ?], R]
def a[R: _effects]: Eff[R, String] =
some("hi")
def b[R: _effects]: Eff[R, String] =
left("No")
def c[R: _effects]: Eff[R, String] =
right[R, String, String]("ok")
def d[R: _effects]: Eff[R, String] =
get
}
object T4 {
import Members.use._
type _effects[R] = members4[Option, Either[String, ?], State[String, ?], Either[Int, ?], R]
def a[R: _effects]: Eff[R, String] =
some("hi")
def b[R: _effects]: Eff[R, String] =
left[R, String, String]("No")(memberIn[Either[String, ?], R])
def c[R: _effects]: Eff[R, String] =
right[R, String, String]("ok")
def d[R: _effects]: Eff[R, String] =
get
def e[R: _effects]: Eff[R, String] =
left(0)
def f[R: _effects]: Eff[R, String] =
right[R, Int, String]("hi")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment