FP in Scala 4 - 4.6,4.7,4.8
This file contains 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
/** | |
* Created by BPK_t on 2015/06/20. | |
*/ | |
object Main { | |
def main(args: Array[String]) { | |
val x1 = MyLeft("AAA") | |
println(x1.map(x => x)) | |
val x2 = MyRight("AAA") | |
println(x2.map(x => x + "BBB")) | |
val x3 = MyLeft(100) | |
println(x3.flatMap(x => x)) | |
val x4 = MyRight(100) | |
println(x4.flatMap(x => MyRight(x))) | |
val x5 = List(MyRight(10), MyRight(20), MyRight(30)) | |
println(sequence(x5)) | |
val x6 = List(MyRight(10), MyLeft(20), MyRight(30)) | |
println(sequence(x6)) | |
val x7 = List("10", "20", "30") | |
println(traverse(x7)(x => MyRight(x.toInt))) | |
val x8 = mkPerson("", -1) | |
println(x8) | |
val x9 = mkPerson2("", -1) | |
println(x9) | |
val x10 = mkPerson2("", 10) | |
println(x10) | |
val x11 = mkPerson2("AAA", -1) | |
println(x11) | |
val x12 = mkPerson2("AAA", 20) | |
println(x12) | |
} | |
//4.7 | |
def sequence[E, A](es:List[MyEither[E, A]]):MyEither[E, List[A]] = es match { | |
case Nil => MyRight(Nil) | |
case _ => es.head.map2(sequence(es.tail))(_ :: _) | |
} | |
//4.7 | |
def traverse[E,A,B](as:List[A])(f:A=>MyEither[E,B]):MyEither[E,List[B]] = { | |
as match { | |
case Nil => MyRight(Nil) | |
case _ => f(as.head).map2(traverse(as.tail)(f))(_ :: _) | |
} | |
} | |
//List 4-10 | |
def mkName(name:String):MyEither[String, Name] = { | |
if (name == "" || name==null) MyLeft("Name is empty") | |
else MyRight(new Name(name)) | |
} | |
//List 4-10 | |
def mkAge(age:Int):MyEither[String, Age] = { | |
if (age < 0) MyLeft("Age is out of Range") | |
else MyRight(new Age(age)) | |
} | |
def mkPerson(name:String, age:Int):MyEither[String, Person] = { | |
mkName(name).map2(mkAge(age))(Person(_,_)) | |
} | |
//4.8 | |
def mkName2(name:String):MyEither[List[String], Name] = { | |
if (name == "" || name==null) MyLeft(List("Name is empty")) | |
else MyRight(new Name(name)) | |
} | |
//4.8 | |
def mkAge2(age:Int):MyEither[List[String], Age] = { | |
if (age < 0) MyLeft(List("Age is out of Range")) | |
else MyRight(new Age(age)) | |
} | |
//4.8 | |
def mkPerson2(name:String, age:Int):MyEither[List[String], Person] = { | |
val _name = mkName2(name) | |
val _age = mkAge2(age) | |
_name.map3(_age)((a,b) => a ::: b) match { | |
case MyRight(x) => _name.map2(_age)(Person(_,_)) | |
case MyLeft(x) => MyLeft(x) | |
} | |
} | |
} | |
// 4.6 | |
sealed trait MyEither[+E, +A] { | |
def map[B](f:A=>B):MyEither[E,B] = { | |
this match { | |
case MyLeft(e) => MyLeft(e) | |
case MyRight(a) => MyRight(f(a)) | |
} | |
} | |
def flatMap[EE>:E,B](f:A=>MyEither[EE,B]): MyEither[EE, B] = { | |
this match { | |
case MyLeft(e) => MyLeft(e) | |
case MyRight(a) => f(a) | |
} | |
} | |
def orElse[EE >: E, B >: A](b: => MyEither[EE, B]): MyEither[EE, B] = { | |
this match { | |
case MyLeft(e) => b | |
case MyRight(a) => this | |
} | |
} | |
def getOrElse[B](f: E => B): MyEither[B, A] = { | |
this match { | |
case MyLeft(e) => MyLeft(f(e)) | |
case MyRight(a) => MyRight(a) | |
} | |
} | |
def getOrElseFlat[AA>:A,B](f: E => MyEither[B, AA]): MyEither[B, AA] = { | |
this match { | |
case MyLeft(e) => f(e) | |
case MyRight(a) => MyRight(a) | |
} | |
} | |
def map2[EE >: E, B, C](b: MyEither[EE, B])(f: (A, B) => C): MyEither[EE, C] = { | |
this.flatMap(x => b.map(y => f(x, y))) | |
} | |
def map3[AA >: A, B, C](b: MyEither[B, AA])(f: (E, B) => C): MyEither[C, AA] = { | |
this.getOrElseFlat(x=> b.getOrElse(y => f(x,y))) | |
} | |
} | |
case class MyLeft[+E](value:E) extends MyEither[E, Nothing] | |
case class MyRight[+A](value:A) extends MyEither[Nothing, A] | |
case class Person(name:Name, age:Age) | |
sealed class Name(val value:String) | |
sealed class Age(val value:Int) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment