public
Last active

Type Classes using type members, rather than type parameters

  • Download Gist
type-class-type-member.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
trait Semigroup_ {
type F
def append(a: F, b: => F): F
}
 
trait Monoid_ extends Semigroup_ {
def zero: F
}
 
trait Functor_ {
self =>
type F[_]
def map[A, B](fa: F[A])(f: A => B): F[B]
def compose(G: Functor_) = new Functor_ {
type F[a] = self.F[G.F[a]]
def map[A, B](fa: F[A])(f: A => B): F[B] = self.map(fa)(G.map(_)(f))
}
}
 
trait Pointed_ extends Functor_ {
def point[A](a: => A): F[A]
}
 
trait Bind_ extends Functor_ {
def bind[A, B](fa: F[A])(f: A => F[B]): F[B]
}
 
trait Monad_ extends Pointed_ with Bind_ {
def map[A, B](fa: F[A])(f: A => B): F[B] = bind(fa)(a => point(f(a)))
}
 
 
sealed abstract trait Ordering
 
object Ordering {
case object LT extends Ordering
case object EQ extends Ordering
case object GT extends Ordering
 
implicit object OrderingMonoid extends Monoid_ {
type F = Ordering
def zero = EQ
def append(a: F, b: => F): F = a match {
case EQ => b
case x => x
}
}
}
 
case class Identity[A](value: A)
 
object Identity {
implicit object IdentityMonad extends Monad_ {
type F[A] = Identity[A]
 
def point[A](a: => A): F[A] = Identity(a)
def bind[A, B](a: F[A])(f: A => F[B]) = f(a.value)
}
}
 
case class State[S, A](run: S => (A, S))
 
object State {
implicit def StateMonad[S] = new Monad_ {
type F[a]=State[S, a]
 
def point[A](a: => A): F[A] = State(s => (a, s))
def bind[A, B](fa: F[A])(f: A => F[B]): F[B] = State{ s =>
val (a, s1) = fa.run(s)
f(a).run(s1)
}
}
}
 
object Alias {
type Semigroup[G] = Semigroup_ { type F = G }
type Monoid[G] = Monoid_ { type F = G }
type Functor[G[_]] = Functor_ { type F[A] = G[A] }
type Pointed[G[_]] = Pointed_ { type F[A] = G[A] }
type Bind[G[_]] = Bind_ { type F[A] = G[A] }
type Monad[G[_]] = Monad_ { type F[A] = G[A] }
 
def ?[A <: AnyRef](implicit a: A): a.type = a
}
 
object Test {
import Alias._
 
// Need the imports here, unfortunately, as the parts of a type don't include the
// RHS of type members, it only includes the type arguments.
import Ordering._
import Identity._
 
?[Monad[Identity]]
?[Semigroup[Ordering]]
 
// No need to explicitly annotate the type arguments to compose,
// as would be needed of it accepted a Functor[F[_]]
?[Functor[Identity]].compose(State.StateMonad[Int])
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.