Skip to content

Commit

Permalink
Remove Pointed, Copointed and ArrId. The existence of these three typ…
Browse files Browse the repository at this point in the history
…e-classes is a bug scalaz#235.

The operations of these former interfaces have been moved to a more appropriate place:
* Pointed operation has been moved to Applicative
* Copointed operation has been moved to Comonad
* ArrId operation has been moved to Category

A short discussion occurred on the mailing list on this issue:
https://groups.google.com/forum/?fromgroups=#!topic/scalaz/7OE_Nsreqq0

Pointed is a bogus type-class for a number of reasons. The first is that it provides no value.
It's only possible law is given by paramericity (c.f. Theorems for Free, Wadler):
    (x, g) => point(map(x)(g)) == pure(g(x))

Copointed and ArrId have similar reasoning applied.

The adversities of these interfaces have long been discussed; most notably between Ed Kmett, Runar Bjarnason and I.
There is consensus that their existence serves no purpose but to attract defective code. This is the primary compulsion for their removal (not so much their uselessness). This bug fix is similar in structure to the removal of the Zero interface (scalaz 6) with the zero operation moved to the Monoid interface. I cannot find the original discussion on this matter, but I do recall that there were more people involved and also unanimous consensus.

Since I was the original author of these unfortunate type-classes, I offer my apologies for their coming to exist. I co-invented these type-classes with Ed (After I had invented them, I looked around for names and found Ed doing the same thing and stole his names!). I hope my apology can be accepted and we can move on.
  • Loading branch information
tonymorris committed Dec 28, 2012
1 parent 0997a07 commit 3d8d4cc
Show file tree
Hide file tree
Showing 83 changed files with 354 additions and 805 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ in Scala flows from left-to-right, can require fewer type annotations.
every possible extension method. This should also help compiler performance,
by reducing the implicit search space.
* Syntax is layered in the same way as type classes. Importing the syntax for, say, `Applicative`
will also provide the syntax for `Pointed` and `Functor`.
will also provide the syntax for `Apply` and `Functor`.

Syntax can be imported in two ways. Firstly, the syntax specialized for a particular instance
of a type class can be imported directly from the instance itself.
Expand Down
11 changes: 5 additions & 6 deletions core/src/main/scala/scalaz/Applicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ package scalaz
* @see [[scalaz.Applicative.ApplicativeLaw]]
*/
////
trait Applicative[F[_]] extends Apply[F] with Pointed[F] { self =>
trait Applicative[F[_]] extends Apply[F] { self =>
////
def point[A](a: => A): F[A]

// alias for point
def pure[A](a: => A): F[A] = point(a)

// derived functions
override def map[A, B](fa: F[A])(f: A => B): F[B] =
Expand Down Expand Up @@ -81,11 +85,6 @@ object Applicative {

////

def applicative[F[_]](p: Pointed[F], a: Apply[F]): Applicative[F] = new Applicative[F] {
def point[A](a: => A): F[A] = p.point(a)
def ap[A,B](fa: => F[A])(f: => F[A => B]): F[B] = a.ap(fa)(f)
}

implicit def monoidApplicative[M:Monoid]: Applicative[({type λ[α] = M})#λ] = Monoid[M].applicative

////
Expand Down
23 changes: 0 additions & 23 deletions core/src/main/scala/scalaz/ArrId.scala

This file was deleted.

4 changes: 2 additions & 2 deletions core/src/main/scala/scalaz/BijectionT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ trait BijectionTFunctions {
type Bijection[A, B] =
BijectionT[Id, Id, A, B]

def liftBijection[F[+_], G[+_], A, B](t: A => B, f: B => A)(implicit PF: Pointed[F], PG: Pointed[G]): BijectionT[F, G, A, B] =
def liftBijection[F[+_], G[+_], A, B](t: A => B, f: B => A)(implicit PF: Applicative[F], PG: Applicative[G]): BijectionT[F, G, A, B] =
bijection(a => PF.point(t(a)), a => PG.point(f(a)))

def bijectionId[F[+_], G[+_], A](implicit PF: Pointed[F], PG: Pointed[G]): BijectionT[F, G, A, A] =
def bijectionId[F[+_], G[+_], A](implicit PF: Applicative[F], PG: Applicative[G]): BijectionT[F, G, A, A] =
liftBijection(x => x, x => x)

def curryB[A, B, C]: Bijection[(A, B) => C, A => B => C] =
Expand Down
18 changes: 14 additions & 4 deletions core/src/main/scala/scalaz/Bitraverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ trait Bitraverse[F[_, _]] extends Bifunctor[F] with Bifoldable[F] { self =>

def leftTraverse[X]: Traverse[({type λ[α] = F[α, X]})#λ] = new Traverse[({type λ[α] = F[α, X]})#λ] {
def traverseImpl[G[_]:Applicative,A,B](fa: F[A, X])(f: A => G[B]): G[F[B, X]] =
bitraverseImpl(fa)(f, x => Pointed[G] point x)
bitraverseImpl(fa)(f, x => Applicative[G] point x)
}

def rightTraverse[X]: Traverse[({type λ[α] = F[X, α]})#λ] = new Traverse[({type λ[α] = F[X, α]})#λ] {
def traverseImpl[G[_]:Applicative,A,B](fa: F[X, A])(f: A => G[B]): G[F[X, B]] =
bitraverseImpl(fa)(x => Pointed[G] point x, f)
bitraverseImpl(fa)(x => Applicative[G] point x, f)
}

class Bitraversal[G[_]](implicit G: Applicative[G]) {
Expand All @@ -68,14 +68,24 @@ trait Bitraverse[F[_, _]] extends Bifunctor[F] with Bifoldable[F] { self =>
def traverseSTrampoline[S, G[_] : Applicative, A, B, C, D](fa: F[A, B])(f: A => State[S, G[C]])(g: B => State[S, G[D]]): State[S, G[F[C, D]]] = {
import Free._
implicit val A = StateT.stateTMonadState[S, Trampoline].compose(Applicative[G])
bitraverse[({type λ[α]=StateT[Trampoline, S, G[α]]})#λ, A, B, C, D](fa)(f(_: A).lift[Trampoline])(g(_: B).lift[Trampoline]).unliftId[Trampoline, G[F[C, D]], S, S]

new State[S, G[F[C, D]]] {
def apply(initial: S) = {
val st = bitraverse[({type λ[α]=StateT[Trampoline, S, G[α]]})#λ, A, B, C, D](fa)(f(_: A).lift[Trampoline])(g(_: B).lift[Trampoline])
st(initial).run
}
}
}

/** Bitraverse `fa` with a `Kleisli[G, S, C]` and `Kleisli[G, S, D]`, internally using a `Trampoline` to avoid stack overflow. */
def bitraverseKTrampoline[S, G[+_] : Applicative, A, B, C, D](fa: F[A, B])(f: A => Kleisli[G, S, C])(g: B => Kleisli[G, S, D]): Kleisli[G, S, F[C, D]] = {
import Free._
implicit val A = Kleisli.kleisliMonadReader[Trampoline, S].compose(Applicative[G])
Kleisli(bitraverse[({type λ[α]=Kleisli[Trampoline, S, G[α]]})#λ, A, B, C, D](fa)(z => Kleisli[Id, S, G[C]](i => f(z)(i)).lift[Trampoline])(z => Kleisli[Id, S, G[D]](i => g(z)(i)).lift[Trampoline]).unliftId[Trampoline, S, G[F[C, D]]] run _)

Kleisli[G, S, F[C, D]](s => {
val kl = bitraverse[({type λ[α]=Kleisli[Trampoline, S, G[α]]})#λ, A, B, C, D](fa)(z => Kleisli[Id, S, G[C]](i => f(z)(i)).lift[Trampoline])(z => Kleisli[Id, S, G[D]](i => g(z)(i)).lift[Trampoline])
kl.run(s).run
})
}

def bifoldLShape[A,B,C](fa: F[A,B], z: C)(f: (C,A) => C)(g: (C,B) => C): (C, F[Unit, Unit]) =
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/scala/scalaz/Category.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package scalaz
*
*/
////
trait Category[=>:[_, _]] extends ArrId[=>:] with Compose[=>:] { self =>
trait Category[=>:[_, _]] extends Compose[=>:] { self =>
def id[A]: A =>: A

////
// TODO GeneralizedCategory, GeneralizedFunctor, et al, from Scalaz6 ?

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/scalaz/Codensity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package scalaz

trait Codensity[F[+_], +A] { self =>
def apply[B](f: A => F[B]): F[B]
def improve(implicit F: Pointed[F]): F[A] =
def improve(implicit F: Applicative[F]): F[A] =
apply(a => F.point(a))
def flatMap[B](k: A => Codensity[F, B]): Codensity[F, B] = {
new Codensity[F, B] {
Expand Down
20 changes: 2 additions & 18 deletions core/src/main/scala/scalaz/Cokleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,7 @@ object Cokleisli extends CokleisliFunctions with CokleisliInstances {
}
}

trait CokleisliInstances1 {
implicit def cokleisliArrId[F[_]](implicit F0: Copointed[F]) = new CokleisliArrId[F] {
override implicit def F = F0
}
}

trait CokleisliInstances0 extends CokleisliInstances1 {
trait CokleisliInstances0 {
implicit def cokleisliCompose[F[_]](implicit F0: Cojoin[F] with Functor[F]) = new CokleisliCompose[F] {
override implicit def F = F0
}
Expand All @@ -64,9 +58,6 @@ trait CokleisliFunctions {

// def redaer[A, B](r: A => B): Redaer[A, B] =
// Cokleisli[A, Identity, B](a => r(a.value))
//
// def ksa[F[_] : Copointed, A]: Cokleisli[A, F, A] =
// Cokleisli(a => Copointed[F].copoint(a))
}

private[scalaz] trait CokleisliMonad[F[_], R] extends Monad[({type λ[α] = Cokleisli[F, R, α]})#λ] {
Expand All @@ -75,13 +66,6 @@ private[scalaz] trait CokleisliMonad[F[_], R] extends Monad[({type λ[α] = Cokl
def bind[A, B](fa: Cokleisli[F, R, A])(f: (A) => Cokleisli[F, R, B]) = fa flatMap f
}


private[scalaz] trait CokleisliArrId[F[_]] extends ArrId[({type λ[α, β] = Cokleisli[F, α, β]})#λ] {
implicit def F: Copointed[F]

override def id[A] = Cokleisli(F.copoint)
}

private[scalaz] trait CokleisliCompose[F[_]] extends Compose[({type λ[α, β] = Cokleisli[F, α, β]})#λ] {
implicit def F: Cojoin[F] with Functor[F]

Expand All @@ -91,12 +75,12 @@ private[scalaz] trait CokleisliCompose[F[_]] extends Compose[({type λ[α, β] =

private[scalaz] trait CokleisliArrow[F[_]]
extends Arrow[({type λ[α, β] = Cokleisli[F, α, β]})#λ]
with CokleisliArrId[F]
with CokleisliCompose[F] {

implicit def F: Comonad[F]

def arr[A, B](f: (A) => B) = Cokleisli(a => f(F.copoint(a)))
def id[A] = Cokleisli(F.copoint)

def first[A, B, C](f: Cokleisli[F, A, B]) =
Cokleisli[F, (A, C), (B, C)](w => (f.run(F.map(w)(ac => ac._1)), F.copoint(w)._2))
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/scala/scalaz/Comonad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ package scalaz
*
*/
////
trait Comonad[F[_]] extends Copointed[F] with Cojoin[F] with Cobind[F] { self =>
trait Comonad[F[_]] extends Cojoin[F] with Cobind[F] { self =>
/** Also known as `extract` / `copure` */
def copoint[A](p: F[A]): A
////

// derived functions

/** alias for `copoint` */
def copure[A](p: F[A]): A = copoint(p)
trait ComonadLaws {
def cobindLeftIdentity[A](fa: F[A])(implicit F: Equal[F[A]]): Boolean =
F.equal(cobind(fa)(copoint), fa)
Expand Down
15 changes: 3 additions & 12 deletions core/src/main/scala/scalaz/Composition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ private[scalaz] trait CompositionFunctor[F[_], G[_]] extends Functor[({type λ[
override def map[A, B](fga: F[G[A]])(f: (A) => B): F[G[B]] = F(fga)(ga => G(ga)(f))
}

private[scalaz] trait CompositionPointed[F[_], G[_]] extends Pointed[({type λ[α] = F[G[α]]})#λ] with CompositionFunctor[F, G] {
implicit def F: Pointed[F]

implicit def G: Pointed[G]

def point[A](a: => A): F[G[A]] = F.point(G.point(a))
}

private[scalaz] trait CompositionApply[F[_], G[_]] extends Apply[({type λ[α] = F[G[α]]})#λ] with CompositionFunctor[F, G] {
implicit def F: Apply[F]

Expand All @@ -25,16 +17,15 @@ private[scalaz] trait CompositionApply[F[_], G[_]] extends Apply[({type λ[α] =
F.apply2(f, fa)((ff, ga) => G.ap(ga)(ff))
}

private[scalaz] trait CompositionApplicative[F[_], G[_]] extends Applicative[({type λ[α] = F[G[α]]})#λ] with CompositionPointed[F, G] with CompositionFunctor[F, G] {
private[scalaz] trait CompositionApplicative[F[_], G[_]] extends Applicative[({type λ[α] = F[G[α]]})#λ] with CompositionApply[F, G] {
implicit def F: Applicative[F]

implicit def G: Applicative[G]

def ap[A, B](fa: => F[G[A]])(f: => F[G[A => B]]): F[G[B]] =
F.apply2(f, fa)((ff, ga) => G.ap(ga)(ff))
def point[A](a: => A): F[G[A]] = F.point(G.point(a))
}

private[scalaz] trait CompositionApplicativePlus[F[_], G[_]] extends ApplicativePlus[({type λ[α] = F[G[α]]})#λ] with CompositionPointed[F, G] with CompositionFunctor[F, G] with CompositionApplicative[F, G] {
private[scalaz] trait CompositionApplicativePlus[F[_], G[_]] extends ApplicativePlus[({type λ[α] = F[G[α]]})#λ] with CompositionApplicative[F, G] {
implicit def F: ApplicativePlus[F]

implicit def G: ApplicativePlus[G]
Expand Down
29 changes: 0 additions & 29 deletions core/src/main/scala/scalaz/Copointed.scala

This file was deleted.

2 changes: 1 addition & 1 deletion core/src/main/scala/scalaz/Coproduct.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ sealed trait Coproduct[F[+_], G[+_], A] {
, x => G.extend(x)(a => rightc(a)))
)

def copoint(implicit F: Copointed[F], G: Copointed[G]): A =
def copoint(implicit F: Comonad[F], G: Comonad[G]): A =
run.fold(F.copoint(_), G.copoint(_))

def contramap[B](f: B => A)(implicit F: Contravariant[F], G: Contravariant[G]): Coproduct[F, G, B] =
Expand Down
20 changes: 5 additions & 15 deletions core/src/main/scala/scalaz/EitherT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,25 +202,19 @@ object EitherT extends EitherTFunctions with EitherTInstances {
apply(F.map(e)(_ fold (\/.left, \/.right)))

/** Evaluate the given value, which might throw an exception. */
def fromTryCatch[F[+_], A](a: => F[A])(implicit F: Pointed[F]): EitherT[F, Throwable, A] = try {
def fromTryCatch[F[+_], A](a: => F[A])(implicit F: Applicative[F]): EitherT[F, Throwable, A] = try {
right(a)
} catch {
case e => left(F.point(e))
}
}

trait EitherTInstances4 {
trait EitherTInstances3 {
implicit def eitherTFunctor[F[+_], L](implicit F0: Functor[F]) = new EitherTFunctor[F, L] {
implicit def F = F0
}
}

trait EitherTInstances3 extends EitherTInstances4 {
implicit def eitherTPointed[F[+_], L](implicit F0: Pointed[F]) = new EitherTPointed[F, L] {
implicit def F = F0
}
}

trait EitherTInstances2 extends EitherTInstances3 {
implicit def eitherTApply[F[+_], L](implicit F0: Apply[F]) = new EitherTApply[F, L] {
implicit def F = F0
Expand Down Expand Up @@ -281,20 +275,16 @@ private[scalaz] trait EitherTFunctor[F[+_], E] extends Functor[({type λ[α]=Eit
override def map[A, B](fa: EitherT[F, E, A])(f: (A) => B): EitherT[F, E, B] = fa map f
}

private[scalaz] trait EitherTPointed[F[+_], E] extends Pointed[({type λ[α]=EitherT[F, E, α]})#λ] with EitherTFunctor[F, E] {
implicit def F: Pointed[F]

def point[A](a: => A): EitherT[F, E, A] = EitherT(F.point(\/-(a)))
}

private[scalaz] trait EitherTApply[F[+_], E] extends Apply[({type λ[α]=EitherT[F, E, α]})#λ] with EitherTFunctor[F, E] {
implicit def F: Apply[F]

override def ap[A, B](fa: => EitherT[F, E, A])(f: => EitherT[F, E, (A) => B]): EitherT[F, E, B] = fa ap f
}

private[scalaz] trait EitherTApplicative[F[+_], E] extends Applicative[({type λ[α]=EitherT[F, E, α]})#λ] with EitherTApply[F, E] with EitherTPointed[F, E] {
private[scalaz] trait EitherTApplicative[F[+_], E] extends Applicative[({type λ[α]=EitherT[F, E, α]})#λ] with EitherTApply[F, E] {
implicit def F: Applicative[F]
def point[A](a: => A): EitherT[F, E, A] = EitherT(F.point(\/-(a)))

}

private[scalaz] trait EitherTMonad[F[+_], E] extends Monad[({type λ[α]=EitherT[F, E, α]})#λ] with EitherTApplicative[F, E] {
Expand Down
10 changes: 3 additions & 7 deletions core/src/main/scala/scalaz/Free.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,9 @@ sealed abstract class Free[S[+_], +A](implicit S: Functor[S]) {
object Trampoline extends TrampolineInstances

trait TrampolineInstances {
implicit val trampolineMonad: Monad[Trampoline] with Copointed[Trampoline] = new Monad[Trampoline] with Copointed[Trampoline] {
implicit val trampolineMonad: Monad[Trampoline] = new Monad[Trampoline] {
override def point[A](a: => A) = return_[Function0, A](a)
def bind[A, B](ta: Trampoline[A])(f: A => Trampoline[B]) = ta flatMap f
def copoint[A](p: Free.Trampoline[A]): A = {
import std.function.function0Instance
p.run
}
}
}

Expand Down Expand Up @@ -217,10 +213,10 @@ trait FreeFunctions {
def reset[A](r: Trampoline[A]): Trampoline[A] = { val a = r.run; return_(a) }

/** Suspend the given computation in a single step. */
def return_[S[+_], A](value: => A)(implicit S: Pointed[S]): Free[S, A] =
def return_[S[+_], A](value: => A)(implicit S: Applicative[S]): Free[S, A] =
Suspend[S, A](S.point(Return[S, A](value)))

def suspend[S[+_], A](value: => Free[S, A])(implicit S: Pointed[S]): Free[S, A] =
def suspend[S[+_], A](value: => Free[S, A])(implicit S: Applicative[S]): Free[S, A] =
Suspend[S, A](S.point(value))

/** A trampoline step that doesn't do anything. */
Expand Down
Loading

0 comments on commit 3d8d4cc

Please sign in to comment.