From 216ad9b15adb8c86706941d1fb7c27dcce383791 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Fri, 12 Feb 2016 23:39:11 -0800 Subject: [PATCH 1/2] Remove required laziness in Prod, fixes #615 --- core/src/main/scala/cats/data/Prod.scala | 27 +++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index f368e1abef..ab5c6036dd 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -5,20 +5,23 @@ package data * [[Prod]] is a product to two independent functor values. * * See: [[https://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf The Essence of the Iterator Pattern]] - */ -sealed trait Prod[F[_], G[_], A] { - def first: F[A] - def second: G[A] -} + */ +final case class Prod[F[_], G[_], A](first: F[A], second: G[A]) + object Prod extends ProdInstances { - def apply[F[_], G[_], A](first0: => F[A], second0: => G[A]): Prod[F, G, A] = new Prod[F, G, A] { - val firstThunk: Eval[F[A]] = Later(first0) - val secondThunk: Eval[G[A]] = Later(second0) - def first: F[A] = firstThunk.value - def second: G[A] = secondThunk.value + type EvalLifted[F[_], A] = Eval[F[A]] + + def always[F[_], G[_], A](first: => F[A], second: => G[A]): Prod[EvalLifted[F, ?], EvalLifted[G, ?], A] = { + val firstThunk: Eval[F[A]] = Always(first) + val secondThunk: Eval[G[A]] = Always(second) + Prod[EvalLifted[F, ?], EvalLifted[G, ?], A](firstThunk, secondThunk) + } + + def later[F[_], G[_], A](first: => F[A], second: => G[A]): Prod[EvalLifted[F, ?], EvalLifted[G, ?], A] = { + val firstThunk: Eval[F[A]] = Later(first) + val secondThunk: Eval[G[A]] = Later(second) + Prod[EvalLifted[F, ?], EvalLifted[G, ?], A](firstThunk, secondThunk) } - def unapply[F[_], G[_], A](x: Prod[F, G, A]): Option[(F[A], G[A])] = - Some((x.first, x.second)) } private[data] sealed abstract class ProdInstances extends ProdInstances0 { From b194bed2c4a3bb75eb63ccb08e2195d2a8dd6d07 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Tue, 1 Mar 2016 23:58:14 -0500 Subject: [PATCH 2/2] Remove Prod helpers for Lazy and Always --- core/src/main/scala/cats/data/Prod.scala | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index ab5c6036dd..4846217368 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -8,21 +8,7 @@ package data */ final case class Prod[F[_], G[_], A](first: F[A], second: G[A]) -object Prod extends ProdInstances { - type EvalLifted[F[_], A] = Eval[F[A]] - - def always[F[_], G[_], A](first: => F[A], second: => G[A]): Prod[EvalLifted[F, ?], EvalLifted[G, ?], A] = { - val firstThunk: Eval[F[A]] = Always(first) - val secondThunk: Eval[G[A]] = Always(second) - Prod[EvalLifted[F, ?], EvalLifted[G, ?], A](firstThunk, secondThunk) - } - - def later[F[_], G[_], A](first: => F[A], second: => G[A]): Prod[EvalLifted[F, ?], EvalLifted[G, ?], A] = { - val firstThunk: Eval[F[A]] = Later(first) - val secondThunk: Eval[G[A]] = Later(second) - Prod[EvalLifted[F, ?], EvalLifted[G, ?], A](firstThunk, secondThunk) - } -} +object Prod extends ProdInstances private[data] sealed abstract class ProdInstances extends ProdInstances0 { implicit def prodAlternative[F[_], G[_]](implicit FF: Alternative[F], GG: Alternative[G]): Alternative[Lambda[X => Prod[F, G, X]]] = new ProdAlternative[F, G] {