Введение в scalaz

45
Введение в Scalaz http://lambdansk.org https://twitter.com/ZhekaKozlov

Upload: john-kozlov

Post on 16-Aug-2015

198 views

Category:

Science


6 download

TRANSCRIPT

Page 1: Введение в Scalaz

Введение в Scalaz

http://lambdansk.org

https://twitter.com/ZhekaKozlov

Page 2: Введение в Scalaz

Scalaz – библиотека, которая приносит концепции Haskell в

Scala

Page 3: Введение в Scalaz

Проекты, использующие Scalaz:

• https://github.com/argonaut-io/argonaut/• https://github.com/tpolecat/doobie• https://github.com/oncue/remotely• https://github.com/scalaz/scalaz-stream• https://github.com/xuwei-k/httpz• https://github.com/http4s/http4s

Page 4: Введение в Scalaz

Функциональные структуры данных, отсутствующие в Scala stdlib:

scalaz.NonEmptyList[A] Непустой список

scalaz.EphemeralStream[A] Правильный Stream(аналог списков в Haskell)

scalaz.FingerTree[V, A] http://staff.city.ac.uk/~ross/papers/FingerTree.html

scalaz.DList[A] Чистофункциональныйаналог ListBuffer

Page 5: Введение в Scalaz

FingerTree[Int, A] Vector[A] TreeMap[Int, A] List[A]

head O(1) O(log32 n) O(log n) O(1)

tail O(1) O(log32 n) O(log n) O(1)

last O(1) O(log32 n) O(log n) O(n)

init O(1) O(log32 n) O(log n) O(n)

get(index) O(log n) O(log32 n) O(log n) O(n)

Page 6: Введение в Scalaz

Функциональные структуры данных, отсутствующие в Scala stdlib:

scalaz.\/[A, B] Правильный Either

scalaz.\&/[A, B] Как Either, но может быть одновременно и A, и B

scalaz.Either3[A, B, C] Как Either, но может быть A, B или C

Page 7: Введение в Scalaz

В ООП доминирует подтиповойполиморфизм:

class Int {def <(other: Int): Boolean = …

}

class Double {def <(other: Double): Boolean = …

}

class String {def <(other: String): Boolean = …

}

Page 8: Введение в Scalaz

В ООП доминирует подтиповойполиморфизм:

class Int {def <(other: Int): Boolean = …

}

class Double {def <(other: Double): Boolean = …

}

class String {def <(other: String): Boolean = …

}

Page 9: Введение в Scalaz

Общее поведение выделяется в класс:

trait Ordered[A] {def <(other: A): Boolean…

}

class Int extends Ordered[Int] { … }class Double extends Ordered[Double] { … }class String extends Ordered[String] { … }

Page 10: Введение в Scalaz

Проблема 1: не можем заранее предугадать, какое поведение нам понадобится:

class Int extends Ordered[Int]with Addable[Int]with Random[Int]with ToJSON[Int]with ToXML[Int]with ToBinary[Int]with …

Page 11: Введение в Scalaz

Проблема 2: не всё общее поведение можно выразить через наследование

trait Zero[A] {def zero: A

}

class Int extends Zero[Int] {def zero = 0

}

Чтобы иметь возможность вызвать zero, нужен экземпляр класса Int

???

Page 12: Введение в Scalaz

Решение: классы типов

trait Addable[A] {def add(a1: A, a2: A): A

}

trait Zero[A] {def zero: A

}

Page 13: Введение в Scalaz

Решение: классы типовobject intInstance

extends Addable[Int]with Zero[Int] {

def add(a1: Int, a2: Int) = a1+a2def zero = 0

}

object stringInstanceextends Addable[String]with Zero[String] {

def add(s1: String, s2: String) = s1+s2def zero = ""

}

Page 14: Введение в Scalaz

scala> intInstance.add(3, 5)res0: Int = 8

scala> stringInstance.zerores1: String = ""

Page 15: Введение в Scalaz

scalaz.Equal[A]

trait Equal[A] {def equal(a1: A, a2: A): Boolean

}

Page 16: Введение в Scalaz

scala> intInstance.equal(3, 3)res0: Boolean = true

scala> stringInstance.equal("s", "s2") res1: Boolean = false

Page 17: Введение в Scalaz

Добавим синтаксического сахару:

implicit class EqualOps[A](a: A)(implicit val e: Equal[A]) {

def ===(other: A) = e.equal(a, other)def /==(other: A) = !e.equal(a, other)

}

Page 18: Введение в Scalaz

scala> 3 === 3res0: Boolean = true

scala> "s" /== "s2"res1: Boolean = true

scala> 3 === "s"<console>:14: error: type mismatch;found : String("s")required: Int

3 === "s"^

Page 19: Введение в Scalaz

scalaz.Order[A]

trait Order[A] extends Equal[A] {def order(a1: A, a2: A): Orderingdef equal(a1: A, a2: A) =order(a1, a2) == EQ

}

sealed trait Orderingcase object LT extends Orderingcase object EQ extends Orderingcase object GT extends Ordering

Page 20: Введение в Scalaz

Принцип использования Scalaz:Когда объявляем класс

class Rational(nom: Int, denom: Int) { … }

… в объекте-компаньоне создаём инстанс, реализующий все необходимые классы типов:

object Rational {implicit object instance

extends Order[Rational]with Numeric[Rational]with … {

def order(r1: Rational, r2: Rational) = ……

}}

Page 21: Введение в Scalaz

scalaz.Enum[A]

trait Enum[A] extends Order[A] {def succ(a: A): Adef pred(a: A): Adef fromToL(f: A, t: A): List[A] = …

}

implicit class EnumOps[A](a: A)(implicit val e: Enum[A]) {

def |-> (to: A) = e.fromToL(a, to)}

Page 22: Введение в Scalaz

scala> 1 |-> 5res0: List[Int] = List(1, 2, 3, 4, 5)

scala> 'a' |-> 'd'res1: List[Char] = List(a, b, c, d)

Page 23: Введение в Scalaz

scalaz.Semigroup[A]

trait Semigroup [A] {def append(a1: A, a2: => A): A

}

implicit class SemigroupOps[A](a: A)(implicit val s: Semigroup[A]) {

def |+| (o: => A) = s.append(a, o)}

Page 24: Введение в Scalaz

scala> 3 |+| 2res0: Int = 5

scala> List(1,2,3) |+| List(4,5)res1: List[Int] = List(1, 2, 3, 4, 5)

scala> "abc" |+| "de"res2: String = abcde

Page 25: Введение в Scalaz

scala> List(1,2,3) ++ "ab"res0: List[AnyVal] = List(1, 2, 3, a, b)

scala> List(1,2,3) |+| "ab"<console>:26: error: type mismatch;found : String("ab")required: List[Int]

List(1,2,3) |+| "ab"^

Page 26: Введение в Scalaz

scalaz.Monoid[A]

trait Monoid [A] extends Semigroup [A] {def zero: A

}

Page 27: Введение в Scalaz

def sum[A](list: List[A])(implicit m: Monoid[A]) =

list.foldLeft(m.zero)(_ |+| _)

Page 28: Введение в Scalaz

scala> sum(List(1,2,3))res0: Int = 6

scala> sum(List("ab","cd","ef"))res1: String = abcdef

scala> sum(List(List(1,2),List(3,4))res2: List[Int] = List(1,2,3,4)

Page 29: Введение в Scalaz

class List[A] {def map[B](f: A => B): List[B]

}

class Vector[A] {def map[B](f: A => B): Vector[B]

}

class Option[A] {def map[B](f: A => B): Option[B]

}

Page 30: Введение в Scalaz

class List[A] {def map[B](f: A => B): List[B]

}

class Vector[A] {def map[B](f: A => B): Vector[B]

}

class Option[A] {def map[B](f: A => B): Option[B]

}

Page 31: Введение в Scalaz

scalaz.Functor[F[_]]

trait Functor[F[_]] {def map[A,B](fa: F[A])(f: A => B): F[B]

}

Конструктор типа

Page 32: Введение в Scalaz

trait Functor[F[_]] {def map[A,B](fa: F[A])(f: A => B): F[B]

}

implicit object listInstance =new Functor[List] {

def map[A,B](fa: List[A])(f: A => B) =fa.map(f)

}

Page 33: Введение в Scalaz

val opt: Option[Int] = for {i ← Some(2)j ← Some(3)

} yield (i + j)

val list: List[(Int, Int)] = for {i ← List(1,2,3)j ← List(5,6)

} yield (i, j)

Page 34: Введение в Scalaz

val opt: Option[Int] = for {i ← Some(2)j ← Some(3)

} yield (i + j)

val list: List[(Int, Int)] = for {i ← List(1,2,3)j ← List(5,6)

} yield (i, j)

Page 35: Введение в Scalaz

trait Apply[F[_]] extends Functor[F] {def apply2[A,B,C](fa: => F[A], fb: => F[B])

(f: (A,B) => C): F[C]}

scalaz.Apply[F[_]]

Page 36: Введение в Scalaz

scala> Apply[Option].apply2(x, y)(_ + _)res0: Option[Int] = Some(5)

scala> Apply[List].apply2(List(1,2,3),List(5,6))((_, _))

res1: List[(Int,Int)] = List((1,5),(1,6),(2,5),(2,6),(3,5),(3,6))

Page 37: Введение в Scalaz

val opt: Option[Int] = Some(5)

val list: List[String] = List("a")

val fut: Future[Double] = Future(3.5)

Page 38: Введение в Scalaz

val opt: Option[Int] = Some(5)

val list: List[String] = List("a")

val fut: Future[Double] = Future(3.5)

Page 39: Введение в Scalaz

trait Pure[F[_]] {def point[A](a: => A): F[A]

}

scalaz.Pure[F[_]]

Был удалён в Scalaz 7

Page 40: Введение в Scalaz

trait Applicative[F[_]] extends Apply[F] {def point[A](a: => A): F[A]

}

scalaz.Applicative[F[_]]

Page 41: Введение в Scalaz

class List[A] {def flatMap[B](f: A => List[B]): List[B]

}

class Vector[A] {def flatMap[B](f: A => Vector[B]): Vector[B]

}

class Option[A] {def flatMap[B](f: A => Option[B]): Option[B]

}

Page 42: Введение в Scalaz

scalaz.Bind[F[_]]

trait Bind[F[_]] extends Apply[F] {def bind[A,B](fa: F[A])

(f: A => F[B]): F[B]}

Page 43: Введение в Scalaz

scala> some(some(5)).joinres0: Option[Int] = Some(5)

scala> List(List(1,2), List(3,4,5)).joinres1: List[Int] = List(1,2,3,4,5)

Page 44: Введение в Scalaz

scalaz.Monad[F[_]]

trait Monad[F[_]]extends Applicative[F]with Bind[F] {

…}

Page 45: Введение в Scalaz