-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace TransLift with MonadTrans #1621
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package cats | ||
|
||
/** | ||
* A type class which abstracts over the ability to lift an M[A] into a | ||
* MonadTransformer | ||
*/ | ||
trait MonadTrans[MT[_[_], _]] { | ||
|
||
/** | ||
* Lift a value of type M[A] into a monad transformer MT[M, A] | ||
*/ | ||
def liftT[M[_]: Monad, A](ma: M[A]): MT[M, A] | ||
} | ||
|
||
object MonadTrans { | ||
def apply[MT[_[_], _]](implicit MT: MonadTrans[MT]): MonadTrans[MT] = MT | ||
} |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ trait AllSyntax | |
with ShowSyntax | ||
with SplitSyntax | ||
with StrongSyntax | ||
with TransLiftSyntax | ||
with MonadTransSyntax | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep in alphabetical order? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
with TraverseFilterSyntax | ||
with TraverseSyntax | ||
with TupleSyntax | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package cats | ||
package syntax | ||
|
||
trait MonadTransSyntax { | ||
implicit final def catsSyntaxMonadTrans[F[_], A](fa: F[A]): MonadTransOps[F, A] = new MonadTransOps(fa) | ||
} | ||
|
||
final class MonadTransOps[F[_], A](val fa: F[A]) extends AnyVal { | ||
def liftT[MT[_[_], _]](implicit F: Monad[F], MT: MonadTrans[MT]): MT[F, A] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about a doctest here? It will provide coverage for both here and the syntax line above. Then you should get green light from codecov There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a test in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pointed out because codecov reported test miss here. Now I see that |
||
MT.liftT(fa) | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package cats | ||
package laws | ||
|
||
trait MonadTransLaws[MT[_[_], _]] { | ||
implicit def MT: MonadTrans[MT] | ||
|
||
def identity[G[_], A](a: A)(implicit G: Monad[G], MTM: Monad[MT[G, ?]]): IsEq[MT[G, A]] = | ||
MT.liftT(G.pure(a)) <-> MTM.pure(a) | ||
|
||
def composition[G[_], A, B](ga: G[A], f: A => G[B])(implicit G: Monad[G], MTM: Monad[MT[G, ?]]): IsEq[MT[G, B]] = | ||
MT.liftT(G.flatMap(ga)(f)) <-> MTM.flatMap(MT.liftT(ga))(a => MT.liftT(f(a))) | ||
} | ||
|
||
object MonadTransLaws { | ||
def apply[MT[_[_], _]](implicit ev: MonadTrans[MT]): MonadTransLaws[MT] = | ||
new MonadTransLaws[MT] { def MT: MonadTrans[MT] = ev } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cats | ||
package laws | ||
package discipline | ||
|
||
import org.scalacheck.{Arbitrary, Cogen, Prop} | ||
import org.typelevel.discipline.Laws | ||
import Prop._ | ||
|
||
trait MonadTransTests[MT[_[_], _]] extends Laws { | ||
def laws: MonadTransLaws[MT] | ||
|
||
def monadTrans[G[_]: Monad, A: Arbitrary: Eq, B: Eq](implicit | ||
MonadMTG: Monad[MT[G, ?]], | ||
ArbGA: Arbitrary[G[A]], | ||
ArbGB: Arbitrary[G[B]], | ||
CogenA: Cogen[A], | ||
EqGA: Eq[G[A]], | ||
EqGB: Eq[G[B]], | ||
EqMTGA: Eq[MT[G, A]], | ||
EqMTGB: Eq[MT[G, B]] | ||
): RuleSet = { | ||
new DefaultRuleSet( | ||
name = "monadTrans", | ||
parent = None, | ||
"monadTrans identity" -> forAll(laws.identity[G, A] _), | ||
"monadTrans composition" -> forAll(laws.composition[G, A, B] _) | ||
) | ||
} | ||
} | ||
|
||
object MonadTransTests { | ||
def apply[MT[_[_], _]: MonadTrans]: MonadTransTests[MT] = | ||
new MonadTransTests[MT] { | ||
def laws: MonadTransLaws[MT] = MonadTransLaws[MT] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing Edward Kmett noted in a talk he gave on monad homomorphisms is that
MonadTrans
provides no constraint that the resultingMT[M, A]
has aMonad
instance. I believe in his talk he fixes this by adding a function taking theMonad[M]
constraint and providing aMonad[MT[M, ?]]
constraint. In Scala it might look something like:Would we want something like that here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scalaz does it. Not sure if it's useful. But it makes sense in theory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would communicate the law: For every lawful
M[_]: Monad
there exists a lawfulMT[M, ?]: Monad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we check such a law? Would be cool if we could rule out the naïve
ListT
for instance.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simple way would be to pick a fixed
M
, e.g.Option
, get theMonad[MT[Option, ?]]
from this method, and then law-check that.A fancier way would be to use existentials or something to be able to vary
M
and do law-checking across all these :-)EDIT Hmm I actually don't know what that would look like in terms of code though.