Created
August 6, 2021 19:30
-
-
Save kitlangton/1d5691e6e273ffb143046debe6af596a to your computer and use it in GitHub Desktop.
This file contains 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 zio | |
object PathDependentTypes { | |
val zio1: ZIO[Any, Nothing, Int] = ZIO.succeed(1) | |
val zio2: ZIO[Any, Nothing, Int] = ZIO.succeed(2) | |
val zio3: ZIO[Any, Nothing, Int] = ZIO.succeed(3) | |
val zio4 = zio1 <*> zio2 <*> zio3 <*> zio1 <*> zio2 | |
def zip[R, E, A, B](left: ZIO[R, E, A], right: ZIO[R, E, B]): ZIO[R, E, (A, B)] = | |
??? | |
object Box1 { | |
type A = Nothing | |
} | |
trait Box { self => | |
type A | |
def value: A | |
def printContents(): Unit = | |
println(value) | |
def tupleBox(that: Box): Box.WithContents[(self.A, that.A)] = | |
new Box { | |
type A = (self.A, that.A) | |
val value = (self.value, that.value) | |
} | |
} | |
object Box { | |
type WithContents[A0] = Box { type A = A0 } | |
def apply[A0](a: A0): Box.WithContents[A0] = | |
new Box { | |
type A = A0 | |
val value = a | |
} | |
} | |
val box = Box(1) | |
val box2 = Box("Adam") | |
val x = box.value + box.value | |
val boxes = List(box, box2) | |
val tupleBox = box.tupleBox(box2) | |
val tupleBox2 = tupleBox | |
val tupleBox3 = tupleBox2 | |
val a = tupleBox3.value | |
tupleBox.printContents() | |
trait Schedule[-Env, -In, +Out] { | |
type State | |
def initial: State | |
def step(in: In, state: State): (State, Out, Decision) | |
} | |
object Schedule { | |
type WithState[-Env, -In, +Out, State0] = Schedule[Env, In, Out] { type State = State0 } | |
} | |
sealed trait Decision | |
case object Done extends Decision | |
case class Continue(delay: Duration) extends Decision | |
trait DomainError | |
trait InvalidPassword extends DomainError | |
trait CouldNotDecrypt extends DomainError | |
trait Union[-In] { | |
type Out | |
def apply(in: In): Out | |
} | |
object Union extends UnionLowPriority1 { | |
type WithOut[In, Out0] = Union[In] { type Out = Out0 } | |
implicit def UnionEitherBoth[A]: Union.WithOut[Either[Either[A, A], Either[A, A]], A] = | |
new Union[Either[Either[A, A], Either[A, A]]] { | |
type Out = A | |
def apply(in: Either[Either[A, A], Either[A, A]]): A = | |
in.fold(_.merge, _.merge) | |
} | |
} | |
trait UnionLowPriority1 extends UnionLowPriority2 { | |
implicit def UnionEitherRight[A]: Union.WithOut[Either[A, Either[A, A]], A] = | |
new Union[Either[A, Either[A, A]]] { | |
type Out = A | |
def apply(in: Either[A, Either[A, A]]): A = | |
in.fold(identity, _.merge) | |
} | |
implicit def UnionEitherLeft[A]: Union.WithOut[Either[Either[A, A], A], A] = | |
new Union[Either[Either[A, A], A]] { | |
type Out = A | |
def apply(in: Either[Either[A, A], A]): A = | |
in.fold(_.merge, identity) | |
} | |
} | |
trait UnionLowPriority2 { | |
implicit def UnionEither[A]: Union.WithOut[Either[A, A], A] = | |
new Union[Either[A, A]] { | |
type Out = A | |
def apply(in: Either[A, A]): A = | |
in.merge | |
} | |
} | |
def unify[In](in: In)(implicit union: Union[In]): union.Out = | |
??? | |
val either1: Either[InvalidPassword, CouldNotDecrypt] = ??? | |
val either2: Either[InvalidPassword, Either[CouldNotDecrypt, InvalidPassword]] = ??? | |
val either3: Either[Either[CouldNotDecrypt, InvalidPassword], InvalidPassword] = ??? | |
val either4: Either[Either[CouldNotDecrypt, InvalidPassword], Either[CouldNotDecrypt, InvalidPassword]] = ??? | |
// val either5: Either[InvalidPassword, Either[CouldNotDecrypt, Either[InvalidPassword, InvalidPassword]]] = ??? | |
val result1 = unify(either1) | |
val result2 = unify(either2) | |
val result3 = unify(either3) | |
val result4 = unify(either4) | |
val result5: DomainError = result4 | |
val myEither: Either[String, Int] = ??? | |
val myOption: Option[List[Int]] = ??? | |
val zio10: ZIO[Any, String, Int] = ZIO.from(myEither) | |
val zio11 = ZIO.from(either4) | |
} | |
trait Size[A] { | |
def size: Int | |
} | |
object Size extends SizeLowPriority { | |
implicit def tupleSize[A, B](implicit first: Size[A], second: Size[B]): Size[(A, B)] = | |
new Size[(A,B)] { | |
def size: Int = | |
first.size + second.size | |
} | |
} | |
trait SizeLowPriority { | |
implicit def anySize[A] = new Size[A] { | |
def size = 1 | |
} | |
} | |
object SizeExamples extends scala.App { | |
def size[In](in: In)(implicit size: Size[In]): Unit = | |
println(s"$in -> ${size.size}") | |
val a = 12 | |
val b = "Hello" | |
val ab = (a, b) | |
val c = true | |
val abab = (ab,ab) | |
val abababab = (abab,abab) | |
size(a) | |
size(b) | |
size(ab) | |
size(abab) | |
size(abababab) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment