Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG/minor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- move `attributeCoelgotM` to `attributeElgotAlgebraM`, updating it to the generalized form.
28 changes: 0 additions & 28 deletions core/src/main/scala/matryoshka/AlgebraOps.scala

This file was deleted.

29 changes: 0 additions & 29 deletions core/src/main/scala/matryoshka/CoalgebraOps.scala

This file was deleted.

34 changes: 0 additions & 34 deletions core/src/main/scala/matryoshka/CofreeOps.scala

This file was deleted.

24 changes: 0 additions & 24 deletions core/src/main/scala/matryoshka/FreeOps.scala

This file was deleted.

12 changes: 6 additions & 6 deletions core/src/main/scala/matryoshka/IdOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ package matryoshka
import scalaz._

sealed class IdOps[A](self: A) {
def hylo[F[_]: Functor, B](f: F[B] => B, g: A => F[A]): B =
def hylo[F[_]: Functor, B](f: Algebra[F, B], g: Coalgebra[F, A]): B =
matryoshka.hylo(self)(f, g)
def hyloM[M[_]: Monad, F[_]: Traverse, B](f: F[B] => M[B], g: A => M[F[A]]):
def hyloM[M[_]: Monad, F[_]: Traverse, B](f: AlgebraM[M, F, B], g: CoalgebraM[M, F, A]):
M[B] =
matryoshka.hyloM(self)(f, g)
def ghylo[F[_]: Functor, W[_]: Comonad, M[_]: Monad, B](
w: DistributiveLaw[F, W],
m: DistributiveLaw[M, F],
f: F[W[B]] => B,
g: A => F[M[A]]):
f: GAlgebra[W, F, B],
g: GCoalgebra[M, F, A]):
B =
matryoshka.ghylo(self)(w, m, f, g)

def chrono[F[_]: Functor, B](
g: F[Cofree[F, B]] => B, f: A => F[Free[F, A]]):
g: GAlgebra[Cofree[F, ?], F, B], f: GCoalgebra[Free[F, ?], F, A]):
B =
matryoshka.chrono(self)(g, f)

Expand All @@ -47,7 +47,7 @@ sealed class IdOps[A](self: A) {
def elgotAna[F[_]: Functor, B](ψ: A => B \/ F[A]): Free[F, B] =
matryoshka.elgotAna(self)(ψ)

def elgot[F[_]: Functor, B](φ: F[B] => B, ψ: A => B \/ F[A]): B =
def elgot[F[_]: Functor, B](φ: Algebra[F, B], ψ: ElgotCoalgebra[B \/ ?, F, A]): B =
matryoshka.elgot(self)(φ, ψ)

def coelgot[F[_]: Functor, B](φ: ((A, F[B])) => B, ψ: A => F[A]): B =
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/matryoshka/Proj.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import scalaz._
/** An extractor to make it easier to pattern-match on arbitrary Recursive
* structures.
*
* NB: This extractor is irrufutable and doesn’t break exhaustiveness checking.
* NB: This extractor is irrefutable and doesn’t break exhaustiveness checking.
*/
object Proj {
def unapply[T[_[_]]: Recursive, F[_]: Functor](obj: T[F]): Some[F[T[F]]] =
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/scala/matryoshka/TraverseT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ import simulacrum.typeclass
def transAnaM[M[_]: Monad, F[_]: Functor, G[_]: Traverse](t: T[F])(f: F[T[F]] => M[G[T[F]]]): M[T[G]] =
traverse(t)(f(_).flatMap(_.traverse(transAnaM(_)(f))))

def transApoM[M[_]: Monad, F[_]: Functor, G[_]: Traverse](t: T[F])(f: F[T[F]] => M[G[T[G] \/ T[F]]]):
M[T[G]] =
traverse(t)(f(_).flatMap(_.traverse(_.fold(_.point[M], transApoM(_)(f)))))

def topDownCataM[F[_]: Traverse, M[_]: Monad, A](
t: T[F], a: A)(
f: (A, T[F]) => M[(A, T[F])]):
Expand Down
154 changes: 154 additions & 0 deletions core/src/main/scala/matryoshka/algebra.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* 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._, Leibniz._, 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)

def attribute(implicit E: Comonad[E], G: Comonad[G], M: Functor[M], F: Functor[F]) =
matryoshka.attribute[E, G, M, F, A](this)

def generalizeElgot[EE[_]: Comonad](
implicit ev: GElgotAlgebraM[E, G, M, F, A] === GAlgebraM[G, M, F, A]):
GElgotAlgebraM[EE, G, M, F, A] =
matryoshka.generalizeW[EE, F[G[A]], M[A]](ev(this).apply)

def generalize[GG[_]: Comonad](implicit EF: Functor[λ[α => E[F[α]]]], ev: GElgotAlgebraM[E, G, M, F, A] === ElgotAlgebraM[E, M, F, A]):
GElgotAlgebraM[E, GG, M, F, A] =
matryoshka.generalizeAlgebra[λ[α => E[F[α]]], GG, Id, M, F, A](ev(this).apply)

def generalizeM[MM[_]: Applicative](
implicit ev: GElgotAlgebraM[E, G, M, F, A] === GElgotAlgebra[E, G, F, A]):
GElgotAlgebraM[E, G, MM, F, A] =
matryoshka.generalizeM[MM, E[F[G[A]]], A](ev(this).apply)

def zip[B](
b: ⇒ GElgotAlgebraM[E, G, M, F, B])(
implicit E: Functor[E], G: Functor[G], M: Applicative[M], F: Functor[F]):
GElgotAlgebraM[E, G, M, F, (A, B)]=
node => (this.f(node ∘ (_ ∘ (_ ∘ (_._1)))) ⊛ b(node ∘ (_ ∘ (_ ∘ (_._2)))))((_, _))
}
object GElgotAlgebraM {
implicit def gElgotAlgebraMZip[E[_]: Functor, G[_]: Functor, M[_]: Applicative, F[_]: Functor]:
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]) =
a.zip(b)
}
}

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)

def generalizeM[MM[_]: Applicative](implicit ev: GElgotCoalgebraM[E, G, M, F, A] === GElgotCoalgebra[E, G, F, A]):
GElgotCoalgebraM[E, G, MM, F, A] =
matryoshka.generalizeM[MM, A, E[F[G[A]]]](ev(this).apply)

def generalizeElgot[EE[_]: Applicative](
implicit M: Functor[M],
ev: GElgotCoalgebraM[E, G, M, F, A] === GCoalgebraM[G, M, F, A]):
GElgotCoalgebraM[EE, G, M, F, A] =
matryoshka.generalizeCoalgebra[M, EE, λ[α => F[G[α]]], A](ev(this).apply)

def generalize[GG[_]: Applicative](implicit MEF: Functor[λ[α => M[E[F[α]]]]], ev: GElgotCoalgebraM[E, G, M, F, A] === ElgotCoalgebraM[E, M, F, A]):
GElgotCoalgebraM[E, GG, M, F, A] =
matryoshka.generalizeCoalgebra[λ[α => M[E[F[α]]]], GG, Id, A](ev(this).apply)
}

// 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 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 {
}

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)
}
Loading