Skip to content

Instantly share code, notes, and snippets.

@bpk-t
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bpk-t/2feb95eebc024348afd8 to your computer and use it in GitHub Desktop.
Save bpk-t/2feb95eebc024348afd8 to your computer and use it in GitHub Desktop.
FP in Scala 4 - 4.6,4.7,4.8
/**
* 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