Skip to content

Commit

Permalink
integrate subset of pr zio#449
Browse files Browse the repository at this point in the history
  • Loading branch information
zalbia committed May 11, 2021
1 parent 07cc79f commit 4bb9936
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 1 deletion.
17 changes: 16 additions & 1 deletion core/shared/src/main/scala/zio/prelude/AssociativeBoth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package zio.prelude

import zio._
import zio.prelude.coherent.AssociativeBothDeriveEqualInvariant
import zio.prelude.newtypes.{AndF, Failure, OrF}
import zio.prelude.newtypes.{AndF, Failure, Nested, OrF}
import zio.stm.ZSTM
import zio.stream.{ZSink, ZStream}
import zio.test.TestResult
Expand Down Expand Up @@ -1158,6 +1158,21 @@ object AssociativeBoth extends LawfulF.Invariant[AssociativeBothDeriveEqualInvar
Id(Id.unwrap(fa) -> Id.unwrap(fb))
}

/**
* The `IdentityBoth` (and `AssociativeBoth`) instance for `Nested[F, G, A]`.
*/
implicit def NestedIdentityBoth[F[+_]: IdentityBoth: Covariant, G[+_]](implicit
G: IdentityBoth[G]
): IdentityBoth[({ type lambda[+A] = Nested[F, G, A] })#lambda] =
new IdentityBoth[({ type lambda[+A] = Nested[F, G, A] })#lambda] {
override def any: Nested[F, G, Any] = Nested(G.any.succeed[F])

override def both[A, B](fa: => Nested[F, G, A], fb: => Nested[F, G, B]): Nested[F, G, (A, B)] =
Nested {
Nested.unwrap[F[G[A]]](fa).zipWith(Nested.unwrap[F[G[B]]](fb))(_ zip _)
}
}

/**
* The `IdentityBoth` (and `AssociativeBoth`) instance for `List`.
*/
Expand Down
17 changes: 17 additions & 0 deletions core/shared/src/main/scala/zio/prelude/Covariant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package zio.prelude

import zio.prelude.coherent.CovariantDeriveEqual
import zio.prelude.newtypes.Nested
import zio.test.TestResult
import zio.test.laws._

Expand Down Expand Up @@ -111,6 +112,22 @@ object Covariant extends LawfulF.Covariant[CovariantDeriveEqual, Equal] {
def apply[F[+_]](implicit covariant: Covariant[F]): Covariant[F] =
covariant

/**
* Constructs the instance for `Covariant[({ type lambda[+A] = Nested[F, G, A] })#lambda]`
* given a pair of pre-existing `Covariant` instances for covariant, higher-kinded type
* parameters `F[+_]` and `G[+_]`.
*/
implicit def NestedCovariant[F[+_], G[+_]](implicit
F: Covariant[F],
G: Covariant[G]
): Covariant[({ type lambda[+A] = Nested[F, G, A] })#lambda] =
new Covariant[({ type lambda[+A] = Nested[F, G, A] })#lambda] {
private lazy val composedCovariant = F.compose(G)

override def map[A, B](f: A => B): Nested[F, G, A] => Nested[F, G, B] = { x: Nested[F, G, A] =>
Nested(composedCovariant.map(f)(Nested.unwrap[F[G[A]]](x)))
}
}
}

trait CovariantSyntax {
Expand Down
22 changes: 22 additions & 0 deletions core/shared/src/main/scala/zio/prelude/Derive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package zio.prelude

import zio.{Cause, Chunk, Exit, NonEmptyChunk}
import zio.prelude.newtypes.Nested

import scala.util.Try

Expand Down Expand Up @@ -47,6 +48,27 @@ object Derive {
def apply[F[_], Typeclass[_]](implicit derive: Derive[F, Typeclass]): Derive[F, Typeclass] =
derive


/**
* The `DeriveEqual` instance for `Id`.
*/
implicit val IdDeriveEqual: Derive[Id, Equal] =
new Derive[Id, Equal] {
override def derive[A: Equal]: Equal[Id[A]] = Id.wrapAll(Equal[A])
}

/**
* The `DeriveEqual` instance for `Nested`.
*/
implicit def NestedDeriveEqual[F[+_], G[+_]](implicit
F: Derive[F, Equal],
G: Derive[G, Equal]
): Derive[({ type lambda[A] = Nested[F, G, A] })#lambda, Equal] =
new Derive[({ type lambda[A] = Nested[F, G, A] })#lambda, Equal] {
override def derive[A: Equal]: Equal[Nested[F, G, A]] =
Equal.NestedEqual(F.derive(G.derive[A]))
}

/**
* The `DeriveEqual` instance for `Chunk`.
*/
Expand Down
12 changes: 12 additions & 0 deletions core/shared/src/main/scala/zio/prelude/Equal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package zio.prelude

import zio.Exit.{Failure, Success}
import zio.prelude.coherent.{HashOrd, HashPartialOrd}
import zio.prelude.newtypes.Nested
import zio.test.TestResult
import zio.test.laws.{Lawful, Laws}
import zio.{Cause, Chunk, Exit, Fiber, NonEmptyChunk, ZTrace}
Expand Down Expand Up @@ -220,6 +221,17 @@ object Equal extends Lawful[Equal] {
def default[A]: Equal[A] =
DefaultEqual

implicit def IdEqual[A: Equal]: Equal[Id[A]] = new Equal[Id[A]] {
override protected def checkEqual(l: Id[A], r: Id[A]): Boolean =
Id.unwrap[A](l) === Id.unwrap[A](r)
}

implicit def NestedEqual[F[+_], G[+_], A](implicit eqFGA: Equal[F[G[A]]]): Equal[Nested[F, G, A]] =
new Equal[Nested[F, G, A]] {
override protected def checkEqual(l: Nested[F, G, A], r: Nested[F, G, A]): Boolean =
eqFGA.checkEqual(Nested.unwrap[F[G[A]]](l), Nested.unwrap[F[G[A]]](r))
}

/**
* `Hash` and `Ord` (and thus also `Equal`) instance for `Boolean` values.
*/
Expand Down
10 changes: 10 additions & 0 deletions core/shared/src/main/scala/zio/prelude/newtypes/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ package object newtypes {

type FailureOut[+A] = FailureOut.Type[A]

/**
* A newtype representing Right-to-left composition of functors.
* If F[_] and G[_] are both Covariant, then Nested[F, G, *] is also a Covariant
* If F[_] and G[_] are both IdentityBoth, then Nested[F, G, *] is also an IdentityBoth
* If F[_] and G[_] are both Traversable, then Nested[F, G, *] is also a Traversable
*/
object Nested extends NewtypeF

type Nested[F[+_], G[+_], +A] = Nested.Type[F[G[A]]]

object Natural extends SubtypeSmart[Int](isGreaterThanEqualTo(0)) {

val one: Natural =
Expand Down

0 comments on commit 4bb9936

Please sign in to comment.