Last active
June 26, 2016 15:26
-
-
Save sshark/935fbc103c9bbb14b3bd to your computer and use it in GitHub Desktop.
A Writer Monad example
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
| trait Monoid[A] { | |
| def append(a1: A, a2: A): A | |
| def empty: A | |
| } | |
| object Monoid { | |
| implicit def ListMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] { | |
| def append(a1: List[A], a2: List[A]) = a1 ::: a2 | |
| def empty = Nil | |
| } | |
| } | |
| case class Logger[LOG, A](log: LOG, value: A) { | |
| def map[B](f: A => B) = { | |
| println("map f=" + f(value)) | |
| Logger(log, f(value)) | |
| } | |
| def flatMap[B](f: A => Logger[LOG, B])(implicit m: Monoid[LOG]) = { | |
| val x = f(value) | |
| println("flatMap x=" + x) | |
| Logger(m.append(log, x.log), x.value) | |
| } | |
| // insert much more | |
| } | |
| object Logger { | |
| def unital[LOG, A](value: A)(implicit m: Monoid[LOG]) = | |
| Logger(m.empty, value) | |
| // insert much more | |
| } | |
| object Util { | |
| // utility | |
| implicit def ListLogUtil[A](a: A) = new { | |
| def ~>[B](b: B) = {println("~> a=" + a + ",b=" + b); Logger(List(a), b)} | |
| def <|~[B](k: A => B) = {println("<|~ a=" + a + ",k(a)=" + k(a));Logger(List(k(a)), a)} | |
| } | |
| def noLog[A](a: A) = | |
| Logger.unital[List[String], A](a) | |
| } | |
| // begin example | |
| /* | |
| $ scala Main 456 | |
| RESULT: 7000 | |
| LOG | |
| --- | |
| adding one to 456 | |
| converting int to string 457 | |
| checking length of 457 for evenness | |
| multiplying 1000 by 7 to produce 7000 | |
| */ | |
| object Main { | |
| import Util._ | |
| def main(args: Array[String]) { | |
| val x = args(0).toInt // parse int from command line | |
| val r = | |
| for(a <- addOne(x); | |
| b <- intString(a); | |
| c <- lengthIsEven(b); | |
| d <- noLog(hundredOrThousand(c)); | |
| e <- times7(d) | |
| ) yield e | |
| println("RESULT: " + r.value) | |
| println | |
| println("LOG") | |
| println("---") | |
| r.log foreach println | |
| } | |
| def addOne(n: Int) = | |
| ("adding one to " + n) ~> (n + 1) | |
| def intString(n: Int) = | |
| ("converting int to string " + n) ~> n.toString | |
| def lengthIsEven(s: String) = | |
| ("checking length of " + s + " for evenness") ~> (s.length % 2 == 0) | |
| def hundredOrThousand(b: Boolean) = // no logging | |
| if(b) 100 else 1000 | |
| def times7(n: Int) = | |
| (n * 7) <|~ ("multiplying " + n + " by 7 to produce " + _) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment