Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Created December 12, 2011 02:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gakuzzzz/1464359 to your computer and use it in GitHub Desktop.
Save gakuzzzz/1464359 to your computer and use it in GitHub Desktop.
型クラスを使わないMonadic
trait Functor[+A, M[A] <: Functor[A, M]] {
def map[B](f: A => B): M[B]
def fmap[B] = map[B] _
}
trait Pointed[M[_] <: Pointed[M]] {
def pure[A](a: A): M[A]
}
trait Applicative[+A, M[A] <: Applicative[A, M]] extends Functor[A, M] with Pointed[M] {
def <*>[B >: A, C](fm: M[B => C]): M[C]
def <*>:[B >: A, C] = <*>[B, C] _
def map[B](f: A => B): M[B] = this <*> pure(f)
def `<$>`[B] = map[B] _
def `<$>:`[B] = map[B] _
}
trait Monad[+A, M[A] <: Monad[A, M]] extends Applicative[A, M] {
def flatMap[B](f: A => M[B]): M[B]
def >>=[B] = flatMap[B] _
def `return`[B] = pure[B] _
def <*>[B >: A, C](fm: M[B => C]): M[C] =
fm flatMap {f => this flatMap {v => pure(f(v))}}
// fm >>= {f => this >>= {v => `return`(f(v))}}
}
trait Semigroup0[M <: Semigroup0[M]] {
def append(a: M): M
}
trait Semigroup1[+A, M[A] <: Semigroup1[A, M]] {
def append[B >: A](a: M[B]): M[B]
}
trait Monoid0[M <: Monoid0[M]] extends Semigroup0[M] {
def zero: M
}
trait Monoid1[+A, M[A] <: Monoid1[A, M]] extends Semigroup1[A, M] {
def zero[B >: A]: M[B]
}
trait MonadPlus[+A, M[A] <: MonadPlus[A, M]] extends Monad[A, M] with Monoid1[A, M]
sealed trait Maybe[+A] extends MonadPlus[A, Maybe] {
def pure[B](b: B): Maybe[B] = if (b == null) Not else Just(b)
def zero[B >: A]: Maybe[B] = Not
}
case class Just[+A](value: A) extends Maybe[A] {
def flatMap[B](f: A => Maybe[B]): Maybe[B] = f(value)
def append[B >: A](a: Maybe[B]): Maybe[B] = this
}
case object Not extends Maybe[Nothing] {
def flatMap[B](f: Nothing => Maybe[B]): Maybe[B] = Not
def append[B >: Nothing](a: Maybe[B]): Maybe[B] = a
}
sealed trait Cons[+A] extends MonadPlus[A, Cons] {
def ::[B >: A](b: B): Cons[B] = Cell(b, this)
def pure[B](b: B): Cons[B] = b :: Empty
def ++[B >: A] = append[B] _
def append[B >: A](a: Cons[B]): Cons[B]
def zero[B >: A]: Cons[B] = Empty
}
case class Cell[+A](head: A, tail: Cons[A]) extends Cons[A] {
def flatMap[B](f: A => Cons[B]): Cons[B] = f(head) ++ (tail flatMap f)
def append[B >: A](a: Cons[B]): Cons[B] = head :: tail ++ a
}
case object Empty extends Cons[Nothing] {
def flatMap[B](f: Nothing => Cons[B]): Cons[B] = Empty
def append[B >: Nothing](a: Cons[B]): Cons[B] = a
}
sealed trait Ordering extends Monoid0[Ordering] {
def zero: Ordering = EQ
}
case object LT extends Ordering {
def append(a: Ordering): Ordering = this
}
case object EQ extends Ordering {
def append(a: Ordering): Ordering = a
}
case object GT extends Ordering {
def append(a: Ordering): Ordering = this
}
scala> for {
| a <- Just("aaa")
| b <- Just("bbb")
| } yield a + b
res0: Maybe[java.lang.String] = Just(aaabbb)
scala> for {
| a <- Just("aaa")
| n <- Not
| b <- Just("bbb")
| } yield a + n + b
res1: Maybe[java.lang.String] = Not
scala> (1 :: 2 :: 3 :: Empty) `<$>` (2 + _)
res2: Cons[Int] = Cell(3,Cell(4,Cell(5,Empty)))
scala> val ff: (Int, Int, Int) => Int = _ + _ + _
ff: (Int, Int, Int) => Int = <function3>
scala> ((ff.curried `<$>:` Just(10)) <*>: Just(20)) <*>: Just(30)
res3: Maybe[Int] = Just(60)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment