Created
July 21, 2014 08:43
-
-
Save t2ru/85ab5d7ce9deed1b6332 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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