Skip to content

Instantly share code, notes, and snippets.

@t2ru
Created July 21, 2014 08:43
Show Gist options
  • Save t2ru/85ab5d7ce9deed1b6332 to your computer and use it in GitHub Desktop.
Save t2ru/85ab5d7ce9deed1b6332 to your computer and use it in GitHub Desktop.
package t
import scalaz._
import Scalaz._
import scala.collection.immutable._
object rwse {
type ErrMsg = String
abstract sealed class Err
case class EmptyErr() extends Err
case class SingleErr(msg: ErrMsg) extends Err
case class MultiErr(errs: List[Err]) extends Err
def consErr(a: Err, b: Err): Err = {
(a, b) match {
case (EmptyErr(), _) => b
case (_, EmptyErr()) => a
case (_, SingleErr(y)) => MultiErr(List(a, b))
case (_, MultiErr(xs)) => MultiErr(a :: xs)
}
}
type Stdout = String
type Stdin = String
type Errorable[+A] = Either[Err, A]
type Var = Map[String, String]
type M[+A] = ReaderWriterStateT[Errorable, Stdin, Stdout, Var, A]
def m[A] = ReaderWriterStateT[Errorable, Stdin, Stdout, Var, A] _
def nop = m((_, s) => Right("", (), s))
def ret[A](v: A) = m((_, s) => Right("", v, s))
def getState = m((_, s) => Right("", s, s))
def putState(s: Var) = m((_, _) => Right("", (), s))
def modifyState(f: Var => Var) = m((r, s) => Right("", (), f(s)))
def fail(msg: ErrMsg) = m((_, _) => Left(SingleErr(msg)))
def empty = m((_, _) => Left(EmptyErr()))
def plus[A](a: M[A], b: M[A]): M[A] = m { (r, s) =>
a.run(r, s) match {
case Right(v) => Right(v)
case Left(e) => b.run(r, s) match {
case Right(v) => Right(v)
case Left(errs) => Left(consErr(e, errs))
}
}
}
def conc[A](progs: M[A]*): M[List[A]] = {
progs.toList match {
case Nil => ret(Nil)
case (prog :: rprogs) => for {
v <- prog
vs <- conc(rprogs: _*)
} yield (v :: vs)
}
}
def alt[A](progs: M[A]*): M[A] = {
progs.toList match {
case Nil => empty
case (prog :: rprogs) => plus(prog, alt(rprogs: _*))
}
}
def runProgram[A](prog: M[A]) = {
prog.run("", Map())
}
def main(args: Array[String]): Unit = {
val prog0 = for {
_ <- modifyState(_ + ("hoge" -> "piyo"))
} yield 1
println("prog0:" + runProgram(prog0))
val prog1 = for {
_ <- modifyState(_ + ("hoge" -> "piyo"))
x <- ret(10)
} yield x
println("prog1:" + runProgram(prog1))
val prog2 = for {
_ <- modifyState(_ + ("hoge" -> "piyo"))
_ <- fail("hogehoge")
x <- ret(10)
} yield x
println("prog2:" + runProgram(prog2))
val prog3 = conc(prog0, prog1)
println("prog3:" + runProgram(prog3))
val prog4 = conc(prog0, fail("f"), prog1)
println("prog4:" + runProgram(prog4))
val prog5 = alt(prog0, fail("f"), prog1)
println("prog5:" + runProgram(prog5))
val prog6 = alt(fail("f"), prog1, fail("f"), prog0)
println("prog6:" + runProgram(prog6))
val prog7 = alt(fail("f"), fail("g"))
println("prog7:" + runProgram(prog7))
val prog8 = alt(fail("f"), alt(fail("a"), fail("b")), fail("g"))
println("prog8:" + runProgram(prog8))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment