Last active
July 19, 2017 14:31
-
-
Save msiegenthaler/1460beb98acfb229f989c2b2746e3c43 to your computer and use it in GitHub Desktop.
atnos eff: combining effects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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