-
Notifications
You must be signed in to change notification settings - Fork 87
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
Class-based algebras. #13
base: master
Are you sure you want to change the base?
Changes from 5 commits
8b1684f
e205537
889c652
64244bb
2d10b6a
dca70ca
89a2247
e904b6e
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 @@ | ||
- move `attributeCoelgotM` to `attributeElgotAlgebraM`, updating it to the generalized form. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,13 +16,27 @@ | |
|
||
package matryoshka | ||
|
||
import scalaz._ | ||
import scalaz.syntax.comonad._ | ||
import scalaz._, Scalaz._ | ||
|
||
sealed class AlgebraOps[F[_], A](self: Algebra[F, A]) { | ||
def generalize[W[_]: Comonad](implicit F: Functor[F]): GAlgebra[W, F, A] = | ||
node => self(node ∘ (_.copoint)) | ||
final class GElgotAlgebraMOps[E[_], G[_], M[_], F[_], A]( | ||
self: GElgotAlgebraM[E, G, M, F, A]) { | ||
|
||
def generalizeElgot[W[_]: Comonad]: ElgotAlgebra[W, F, A] = | ||
w => self(w.copoint) | ||
def attribute(implicit E: Comonad[E], G: Comonad[G], M: Functor[M], F: Functor[F]) = | ||
matryoshka.attribute[E, G, M, F, A](self) | ||
} | ||
|
||
final class GAlgebraMOps[G[_], M[_], F[_], A](self: GAlgebraM[G, M, F, A]) { | ||
def generalizeElgot[E[_]: Comonad]: GElgotAlgebraM[E, G, M, 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. For operations like this that apply to a final class GElgotAlgebraM[E[_], G[_], M[_], F[_], A](f: E[F[G[A]]] => M[A]) {
def generalizeElgot[EE[_]: Comonad](implicit ev: GElgotAlgebraM[E, G, M, F, A] === GAlgebraM[G, M, F, A]): GElgotAlgebraM[EE, G, M, F, A] =
new GElgotAlgebraM(matryoshka.generalizeW[E, F[G[A]], M[A]](f))
} 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 tried this (fixing the final 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. Ah, sorry, you'll want to use the evidence parameter to convert the value, try new GElgotAlgebraM(matryoshka.generalizeW[E, F[G[A]], M[A]](ev(self).f)) |
||
matryoshka.generalizeW[E, F[G[A]], M[A]](self) | ||
} | ||
|
||
final class ElgotAlgebraMOps[E[_], M[_], F[_], A](self: ElgotAlgebraM[E, M, F, A]) { | ||
def generalize[G[_]: Comonad](implicit EF: Functor[λ[α => E[F[α]]]]): | ||
GElgotAlgebraM[E, G, M, F, A] = | ||
matryoshka.generalizeAlgebra[λ[α => E[F[α]]], G, Id, M, F, A](self) | ||
} | ||
|
||
final class GElgotAlgebraOps[E[_], G[_], F[_], A](self: GElgotAlgebra[E, G, F, A]) { | ||
def generalizeM[M[_]: Applicative]: GElgotAlgebraM[E, G, M, F, A] = | ||
matryoshka.generalizeM[M, E[F[G[A]]], A](self) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,14 +16,20 @@ | |
|
||
package matryoshka | ||
|
||
import scalaz._ | ||
import scalaz.syntax.monad._ | ||
import scalaz._, Scalaz._ | ||
|
||
sealed class CoalgebraOps[F[_], A](self: Coalgebra[F, A]) { | ||
def generalize[M[_]: Monad](implicit F: Functor[F]): GCoalgebra[M, F, A] = | ||
self(_).map(_.map(_.point[M])) | ||
final class GElgotCoalgebraOps[E[_], G[_], F[_], A](self: GElgotCoalgebra[E, G, 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. Same comments here regarding making these methods on |
||
def generalizeM[M[_]: Applicative]: | ||
GElgotCoalgebraM[E, G, M, F, A] = | ||
matryoshka.generalizeM[M, A, E[F[G[A]]]](self) | ||
} | ||
|
||
def generalizeM[M[_]: Monad]: CoalgebraM[M, F, A] = self(_).point[M] | ||
final class ElgotCoalgebraMOps[E[_], M[_], F[_], A](self: ElgotCoalgebraM[E, M, F, A]) { | ||
def generalize[G[_]: Applicative](implicit MEF: Functor[λ[α => M[E[F[α]]]]]): GElgotCoalgebraM[E, G, M, F, A] = | ||
matryoshka.generalizeCoalgebra[λ[α => M[E[F[α]]]], G, Id, A](self) | ||
} | ||
|
||
def generalizeElgot[M[_]: Monad]: CoalgebraM[M, F, A] = self.generalizeM | ||
final class GCoalgebraMOps[G[_], M[_], F[_], A](self: GCoalgebraM[G, M, F, A]) { | ||
def generalizeElgot[E[_]: Applicative](implicit M: Functor[M]): GElgotCoalgebraM[E, G, M, F, A] = | ||
matryoshka.generalizeCoalgebra[M, E, λ[α => F[G[α]]], A](self) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* | ||
* Copyright 2014 - 2015 SlamData Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package matryoshka | ||
|
||
import scala.Function1 | ||
|
||
import scalaz._, Scalaz._ | ||
|
||
/** The most general algebra, using both generalized and Elgot comonads as | ||
* well as a monad. | ||
*/ | ||
final class GElgotAlgebraM[E[_], G[_], M[_], F[_], A](f: E[F[G[A]]] => M[A]) | ||
extends Function1[E[F[G[A]]], M[A]] { | ||
def apply(v1: E[F[G[A]]]) = f(v1) | ||
} | ||
object GElgotAlgebraM { | ||
implicit def zip[E[_]: Functor, G[_]: Functor, M[_]: Applicative, F[_]: Functor]: | ||
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 the potential here for On further inspection maybe this was intentional. 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. Not intentional as such … but I have never managed to have this implicit found, so I always have to explicitly refer to I would be happy to give it a long name if it means that implicit search will find it, but no luck so far. 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. You could also add |
||
Zip[GElgotAlgebraM[E, G, M, F, ?]] = | ||
new Zip[GElgotAlgebraM[E, G, M, F, ?]] { | ||
def zip[A, B]( | ||
a: ⇒ GElgotAlgebraM[E, G, M, F, A], | ||
b: ⇒ GElgotAlgebraM[E, G, M, F, B]) = | ||
node => (a(node ∘ (_ ∘ (_ ∘ (_._1)))) ⊛ b(node ∘ (_ ∘ (_ ∘ (_._2)))))((_, _)) | ||
} | ||
} | ||
|
||
sealed class GElgotCoalgebraM[E[_], G[_], M[_], F[_], A](f: A => M[E[F[G[A]]]]) | ||
extends Function1[A, M[E[F[G[A]]]]] { | ||
def apply(v1: A) = f(v1) | ||
} | ||
|
||
// NB: This class is needed to avoid the `Id[Id[_]]` “cyclic alias” issue. | ||
final class GCoalgebra[G[_], F[_], A](f: A => F[G[A]]) | ||
extends GElgotCoalgebraM[Id, G, Id, F, A](f) | ||
|
||
sealed trait ZeroIdInstances { | ||
implicit def toGElgotAlgebraM[E[_], G[_], M[_], F[_], A](f: E[F[G[A]]] => M[A]): GElgotAlgebraM[E, G, M, F, A] = | ||
new GElgotAlgebraM[E, G, M, F, A](f) | ||
|
||
implicit def toGElgotAlgebraMOps[E[_], G[_], M[_], F[_], A]( | ||
a: GElgotAlgebraM[E, G, M, F, A]): | ||
GElgotAlgebraMOps[E, G, M, F, A] = | ||
new GElgotAlgebraMOps[E, G, M, F, A](a) | ||
|
||
implicit def toGElgotCoalgebraM[E[_], G[_], M[_], F[_], A](f: A => M[E[F[G[A]]]]): GElgotCoalgebraM[E, G, M, F, A] = | ||
new GElgotCoalgebraM[E, G, M, F, A](f) | ||
|
||
} | ||
|
||
sealed trait OneIdInstances extends ZeroIdInstances { | ||
implicit def toGElgotAlgebraOps[E[_], G[_], F[_], A]( | ||
a: GElgotAlgebra[E, G, F, A]): | ||
GElgotAlgebraOps[E, G, F, A] = | ||
new GElgotAlgebraOps[E, G, F, A](a) | ||
|
||
implicit def toElgotAlgebraMOps[E[_], M[_], F[_], A]( | ||
a: ElgotAlgebraM[E, M, F, A]): | ||
ElgotAlgebraMOps[E, M, F, A] = | ||
new ElgotAlgebraMOps[E, M, F, A](a) | ||
|
||
implicit def toGAlgebraMOps[G[_], M[_], F[_], A](a: GAlgebraM[G, M, F, A]): | ||
GAlgebraMOps[G, M, F, A] = | ||
new GAlgebraMOps[G, M, F, A](a) | ||
|
||
|
||
implicit def toGElgotCoalgebraOps[E[_], G[_], F[_], A]( | ||
a: GElgotCoalgebra[E, G, F, A]): | ||
GElgotCoalgebraOps[E, G, F, A] = | ||
new GElgotCoalgebraOps[E, G, F, A](a) | ||
|
||
implicit def toElgotCoalgebraMOps[E[_], M[_], F[_], A]( | ||
a: ElgotCoalgebraM[E, M, F, A]): | ||
ElgotCoalgebraMOps[E, M, F, A] = | ||
new ElgotCoalgebraMOps[E, M, F, A](a) | ||
|
||
implicit def toGCoalgebraMOps[G[_], M[_], F[_], A](a: GCoalgebraM[G, M, F, A]): | ||
GCoalgebraMOps[G, M, F, A] = | ||
new GCoalgebraMOps[G, M, F, A](a) | ||
} | ||
|
||
sealed trait TwoIdInstances extends OneIdInstances { | ||
// FIXME: somehow this causes an ambiguous implicit with a lower priority | ||
// implicit. | ||
// implicit def toElgotAlgebra[E[_], F[_], A](f: E[F[A]] => A): | ||
// ElgotAlgebra[E, F, A] = | ||
// new GElgotAlgebraM[E, Id, Id, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toElgotAlgebraU[E[_[_], _], F[_], A, X[_]](f: E[X, F[A]] => A): | ||
ElgotAlgebra[E[X, ?], F, A] = | ||
new GElgotAlgebraM[E[X, ?], Id, Id, F, A](f) | ||
|
||
implicit def toElgotCoalgebra[E[_], F[_], A](f: A => E[F[A]]): | ||
ElgotCoalgebra[E, F, A] = | ||
new GElgotCoalgebraM[E, Id, Id, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toElgotCoalgebraU[E[_[_], _], F[_], A, X[_]](f: A => E[X, F[A]]): | ||
ElgotCoalgebra[E[X, ?], F, A] = | ||
new GElgotCoalgebraM[E[X, ?], Id, Id, F, A](f) | ||
|
||
implicit def toGAlgebra[G[_], F[_], A](f: F[G[A]] => A): GAlgebra[G, F, A] = | ||
new GElgotAlgebraM[Id, G, Id, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toGAlgebraU[G[_[_], _], F[_], A, X[_]](f: F[G[X, A]] => A): | ||
GAlgebra[G[X, ?], F, A] = | ||
new GElgotAlgebraM[Id, G[X, ?], Id, F, A](f) | ||
|
||
implicit def toGCoalgebra[G[_], F[_], A](f: A => F[G[A]]): | ||
GCoalgebra[G, F, A] = | ||
new GCoalgebra[G, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toGCoalgebraU[G[_[_], _], F[_], A, X[_]](f: A => F[G[X, A]]): | ||
GCoalgebra[G[X, ?], F, A] = | ||
new GCoalgebra[G[X, ?], F, A](f) | ||
|
||
implicit def toAlgebraM[M[_], F[_], A](f: F[A] => M[A]): AlgebraM[M, F, A] = | ||
new GElgotAlgebraM[Id, Id, M, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toAlgebraMU[M[_[_], _], F[_], A, X[_]](f: F[A] => M[X, A]): | ||
AlgebraM[M[X, ?], F, A] = | ||
new GElgotAlgebraM[Id, Id, M[X, ?], F, A](f) | ||
|
||
implicit def toCoalgebraM[M[_], F[_], A](f: A => M[F[A]]): | ||
CoalgebraM[M, F, A] = | ||
new GElgotCoalgebraM[Id, Id, M, F, A](f) | ||
// Poor man’s unapply trick | ||
implicit def toCoalgebraMU[M[_[_], _], F[_], A, X[_]](f: A => M[X, F[A]]): | ||
CoalgebraM[M[X, ?], F, A] = | ||
new GElgotCoalgebraM[Id, Id, M[X, ?], F, A](f) | ||
} | ||
|
||
trait ThreeIdInstances extends TwoIdInstances { | ||
implicit def toAlgebra[F[_], A](f: F[A] => A): Algebra[F, A] = | ||
new GElgotAlgebraM[Id, Id, Id, F, A](f) | ||
|
||
implicit def toCoalgebra[F[_], A](f: A => F[A]): Coalgebra[F, A] = | ||
new GCoalgebra[Id, F, A](f) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,9 @@ trait CofreeInstances { | |
implicit def cofreeShow[F[_], A: Show](implicit F: (Show ~> λ[α => Show[F[α]]])): | ||
Show[Cofree[F, A]] = | ||
Show.shows(cof => "(" + cof.head.show + ", " + F(cofreeShow).shows(cof.tail) + ")") | ||
|
||
implicit def toCofreeOps[F[_], A](a: Cofree[F, A]): CofreeOps[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. I think you could make |
||
new CofreeOps[F, A](a) | ||
} | ||
|
||
object cofree extends CofreeInstances |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,9 @@ trait FreeInstances { | |
_.point[Free[G, ?]].point[M], | ||
f(_).map(Free.liftF(_).join)) | ||
} | ||
|
||
implicit def toFreeOps[F[_], A](a: Free[F, A]): FreeOps[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. Same comment as for |
||
new FreeOps[F, A](a) | ||
} | ||
|
||
object free extends FreeInstances |
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.
As
GElgotAlgebraM
is now a class, this could be added as a method therein to avoid having to define thisOps
class.