Advertisement
Guest User

Untitled

a guest
Jun 13th, 2017
538
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.66 KB | None | 0 0
  1. package me.ngrid.cats
  2.  
  3. import cats._
  4. import cats.data.Validated.{Invalid, Valid}
  5. import cats.data._
  6. import cats.instances.all._
  7. import cats.syntax.all._
  8.  
  9. import scala.concurrent.ExecutionContext.Implicits.global
  10. import scala.concurrent.duration._
  11. import scala.concurrent.{Await, Future}
  12. //import scala.language.postfixOps
  13.  
  14. object CatsPractice {
  15.  
  16. def foldRight[A, B](as: List[A], acc: B)(fn: (A, B) => B): B =
  17. foldRight(as, Eval.now(acc))(fn).value
  18.  
  19. def foldRight[A, B](as: List[A], acc: Eval[B])(fn: (A, B) => B): Eval[B] = {
  20. as match {
  21. case head :: tail =>
  22. val a = acc.map(x => fn(head, x))
  23. Eval.defer(foldRight(tail, a)(fn))
  24. case Nil =>
  25. acc
  26. }
  27. }
  28.  
  29. def main(args: Array[String]): Unit = {
  30. println(foldRight((0 to 50000).toList, 0) { (l, a) =>
  31. a + l
  32. })
  33. }
  34. }
  35.  
  36. object LoginHacking {
  37.  
  38. case class Db(usernames: Map[Int, String], passwords: Map[String, String])
  39.  
  40. type DbReader[A] = Reader[Db, A]
  41.  
  42. def findUsername(userId: Int): DbReader[Option[String]] = Reader((db: Db) =>
  43. db.usernames.get(userId)
  44. )
  45.  
  46. def checkPassword(username: String, password: String): DbReader[Boolean] =
  47. Reader((db: Db) => db.passwords.get(username).contains(password))
  48.  
  49. def checkLogin(userId: Int, password: String): DbReader[Boolean] =
  50. for {
  51. uname <- findUsername(userId)
  52. check <- uname.fold(false.pure[DbReader])(checkPassword(_, password))
  53. } yield check
  54. }
  55.  
  56. object PostfixCalculator {
  57.  
  58. type CalcState[A] = State[List[Int], A]
  59.  
  60. def evalOne(s: Char): CalcState[Int] = s match {
  61. case '*' => operator(_ * _)
  62. case '+' => operator(_ + _)
  63. case '-' => operator(_ - _)
  64. case '/' => operator(_ / _)
  65. case num => constant(num.toString.toInt)
  66. }
  67.  
  68. def operator(f: (Int, Int) => Int): CalcState[Int] = State {
  69. case one :: two :: tail =>
  70. val x = f(one, two)
  71. (x :: tail, x)
  72. case x => (x, -1)
  73. }
  74.  
  75. def constant(v: Int): CalcState[Int] = State { x =>
  76. (v :: x, v)
  77. }
  78.  
  79. def evalAll(l: Seq[Char]): CalcState[Int] = {
  80. l.map(evalOne).foldLeft(0.pure[CalcState]) {
  81. _ followedBy _
  82. }
  83. }
  84.  
  85. def main(args: Array[String]): Unit = {
  86. println(evalAll("12+3*6+").runA(Nil).value)
  87. println(evalAll("").runA(Nil).value)
  88. }
  89. }
  90.  
  91.  
  92. object BranchingMonad {
  93.  
  94. sealed trait Tree[+A]
  95.  
  96. final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
  97.  
  98. final case class Leaf[A](value: A) extends Tree[A]
  99.  
  100. final case class Empty[A]() extends Tree[A]
  101.  
  102. def branch[A](left: Tree[A], right: Tree[A]): Tree[A] =
  103. Branch(left, right)
  104.  
  105. def leaf[A](value: A): Tree[A] =
  106. Leaf(value)
  107.  
  108. def empty[A]: Tree[A] = Empty()
  109.  
  110.  
  111. implicit val monadLike: Monad[Tree] = new Monad[Tree] {
  112. override def flatMap[A, B](fa: Tree[A])(f: (A) => Tree[B]): Tree[B] = fa match {
  113. case Branch(left, right) => Branch(flatMap(left)(f), flatMap(right)(f))
  114. case Leaf(value) => f(value)
  115. case _: Empty[_] => Empty()
  116. }
  117.  
  118. override def tailRecM[A, B](a: A)(f: (A) => Tree[Either[A, B]]): Tree[B] = {
  119. f(a) match {
  120. case Branch(left, right) =>
  121. Branch(
  122. flatMap(left) {
  123. case Left(v) => tailRecM(v)(f)
  124. case Right(v) => pure(v)
  125. },
  126. flatMap(right) {
  127. case Left(v) => tailRecM(v)(f)
  128. case Right(v) => pure(v)
  129. }
  130. )
  131. case Leaf(Left(l)) => tailRecM(l)(f)
  132. case Leaf(Right(r)) => pure(r)
  133. case _: Empty[_] => Empty()
  134. }
  135. }
  136.  
  137. override def pure[A](x: A): Tree[A] = Leaf(x)
  138. }
  139.  
  140. def main(args: Array[String]): Unit = {
  141. println {
  142. for {
  143. a <- branch(leaf(100), empty)
  144. b <- branch(leaf(a - 10), leaf(a + 10))
  145. c <- branch(leaf(b - 1), leaf(b + 1))
  146. } yield b
  147. }
  148. }
  149. }
  150.  
  151.  
  152. object MonadsTransformAndRoll {
  153.  
  154. //type Response[A] = Future[Either[String, A]]
  155. type Response[A] = EitherT[Future, String, A]
  156.  
  157. val powerLevels = Map(
  158. "Jazz" -> 6,
  159. "Bumblebee" -> 8,
  160. "Hot Rod" -> 10
  161. )
  162.  
  163. def getPowerLevel(autobot: String): Response[Int] = {
  164. powerLevels.get(autobot) match {
  165. case Some(v) => v.pure[Response]
  166. case None => EitherT.left(Future(s"$autobot is unreacheable at this moment"))
  167. }
  168. }
  169.  
  170. def canSpecialMove(ally1: String, ally2: String): Response[Boolean] = {
  171. for {
  172. a <- getPowerLevel(ally1)
  173. b <- getPowerLevel(ally2)
  174. } yield a + b > 15
  175. }
  176.  
  177. def tacticalReport(ally1: String, ally2: String): String = {
  178. val f = canSpecialMove(ally1, ally2).map {
  179. case true => s"$ally1 and $ally2 are ready to rollout"
  180. case false => s"$ally1 and $ally2 are still charging"
  181. }
  182.  
  183. Await.result(f.value, 1.seconds) match {
  184. case Left(s) => "Comms Error: " + s
  185. case Right(s) => s
  186. }
  187. }
  188.  
  189. def main(args: Array[String]): Unit = {
  190. println(tacticalReport("Jazz", "Hot Rod"))
  191. println(tacticalReport("Bumblebee", "Jazz"))
  192. println(tacticalReport("Bumblebee", "Optimus"))
  193. }
  194. }
  195.  
  196. object WooohCartesians {
  197.  
  198. case class Cat(name: String, born: Int, color: String)
  199.  
  200. def main(args: Array[String]): Unit = {
  201. val garf = (Option("Garfield") |@| Option(21) |@| Option("Orange")).map(Cat.apply)
  202. // val garf = (Option("Garfield") |@| None |@| Option("Orange")).map(Cat.apply)
  203. println(garf)
  204. }
  205. }
  206.  
  207.  
  208. object CartisianComposition {
  209.  
  210. case class Cat(name: String, dob: Int, favoriteFood: List[String])
  211.  
  212. implicit val catMonoid = (
  213. Monoid[String] |@| Monoid[Int] |@| Monoid[List[String]]
  214. )
  215. //Why do we need an imap here instead of just map?
  216. // .map(Cat.apply)
  217. .imap(Cat.apply)(x => (x.name, x.dob, x.favoriteFood))
  218.  
  219. def main(args: Array[String]): Unit = {
  220. val garfield = Cat("Garfield", 1978, List("Lasagne"))
  221. val heathcliff = Cat("Heathcliff", 1988, List("Junk Food"))
  222.  
  223. println(garfield |+| heathcliff)
  224. }
  225. }
  226.  
  227. object FormValidation {
  228.  
  229. case class User(name: String, age: Int)
  230.  
  231. type ErrorOr[A] = Either[Vector[String], A]
  232. type AllErrorsOr[A] = Validated[Vector[String], A]
  233.  
  234. def main(args: Array[String]): Unit = {
  235. println(readUser {
  236. Map(
  237. "name" -> "nick",
  238. "age" -> "27"
  239. )
  240. })
  241.  
  242.  
  243. println(readUser {
  244. Map(
  245. "name" -> "",
  246. "age" -> "-7"
  247. )
  248. })
  249. }
  250.  
  251. def readUser(m: Map[String, String]): AllErrorsOr[User] = {
  252. val v = readName(m).toValidated |@| readAge(m).toValidated
  253. v.map(User.apply)
  254. }
  255.  
  256. def readName(m: Map[String, String]): ErrorOr[String] = {
  257. val v = for {
  258. str <- m.readValue("name")
  259. _ <- nonBlank(str)
  260. } yield str
  261.  
  262. v.leftMap(_.map(x => "name: " + x))
  263. }
  264.  
  265. def readAge(m: Map[String, String]): ErrorOr[Int] = {
  266. val v = for {
  267. str <- m.readValue("age")
  268. i <- parseInt(str)
  269. _ <- nonNegative(i)
  270. } yield i
  271.  
  272. v.leftMap(_.map(x => "age: " + x))
  273. }
  274.  
  275. def nonBlank(s: String): ErrorOr[String] = {
  276. if (s.isEmpty) Vector(s"field was empty").asLeft
  277. else s.asRight
  278. }
  279.  
  280. def parseInt(s: String): ErrorOr[Int] = {
  281. Either.catchOnly[NumberFormatException](s.toInt).
  282. leftMap(_ => Vector(s"$s is not a number"))
  283. }
  284.  
  285. def nonNegative(i: Int): ErrorOr[Int] = {
  286. if (i < 0) Vector(s"$i is negative").asLeft
  287. else i.asRight
  288. }
  289.  
  290. implicit class MapWithErrors[K, V](m: Map[K, V]) {
  291. def readValue(k: K): ErrorOr[V] = {
  292. m.get(k) match {
  293. case Some(v) => v.asRight
  294. case None => Vector(s"property $k was not found").asLeft
  295. }
  296. }
  297. }
  298.  
  299. }
  300.  
  301. object Folding {
  302. def main(args: Array[String]): Unit = {
  303. val l = List(1, 2, 3)
  304. println(l.foldLeft(List.empty[Int])((x, y) => y :: x))
  305. println(l.foldRight(List.empty[Int])((x, y) => x :: y))
  306. }
  307.  
  308. case class HyperList[T](l: T*) {
  309. def map[U](f: T => U): HyperList[U] = {
  310. val n = l.foldRight(List.empty[U])((i, a) => f(i) :: a)
  311. HyperList(n: _*)
  312. }
  313.  
  314. def flatMap[U](f: T => HyperList[U]): HyperList[U] = {
  315. val out = l.foldRight(List.empty[U]) { (i, a) =>
  316. f(i).l ++: a
  317. }
  318. HyperList(out: _*)
  319. }
  320.  
  321. def filter(f: T => Boolean): HyperList[T] = {
  322. val out = l.foldRight(List.empty[T]) { (i, a) =>
  323. if (f(i)) i :: a else a
  324. }
  325. HyperList(out: _*)
  326. }
  327.  
  328. def sum(implicit m: Monoid[T]): T = {
  329. l.foldRight(m.empty)(m.combine)
  330. }
  331. }
  332.  
  333. }
  334.  
  335. object AsyncTesting {
  336.  
  337. trait UptimeClient[F[_]] {
  338. def getUptime(hostname: String): F[Int]
  339. }
  340.  
  341. class TestUptimeClient(hosts: Map[String, Int]) extends UptimeClient[Id] {
  342. override def getUptime(hostname: String): Int = {
  343. hosts.getOrElse(hostname, 0)
  344. }
  345. }
  346.  
  347. class UptimeService[F[_] : Applicative](client: UptimeClient[F]) {
  348. def getTotalUptime(hostnames: List[String]): F[Int] = {
  349. hostnames.traverse(client.getUptime).map(_.sum)
  350. }
  351. }
  352.  
  353. def main(args: Array[String]): Unit = {
  354. val hosts = Map("host1" -> 10, "host2" -> 6)
  355. val client = new TestUptimeClient(hosts)
  356. val svc = new UptimeService(client)
  357. val actual = svc.getTotalUptime(hosts.keys.toList)
  358. val expected = hosts.values.toList.sum
  359. assert(actual == expected)
  360. }
  361. }
  362.  
  363. object PygmyHadoop {
  364. val concurrency = Runtime.getRuntime.availableProcessors()
  365.  
  366. def foldMap[A, B: Monoid](v: Vector[A])(f: A => B): B = {
  367. v.foldLeft(Monoid[B].empty)((a, i) => a |+| f(i))
  368. }
  369.  
  370. def parallelFoldMap[A, B: Monoid](v: Vector[A])(f: A => B): Future[B] = {
  371. val n = (1.0 * v.length / concurrency).ceil.toInt
  372.  
  373. // val m: Future[Vector[B]] = v.grouped(n).map { x =>
  374. // Future {
  375. // Foldable[Vector].foldLeft(x, Monoid[B].empty)((a, i) => a |+| f(i))
  376. // }
  377. // }.toVector.sequence
  378.  
  379. // m map { x =>
  380. // x.foldLeft(Monoid[B].empty)((a, i) => a |+| i)
  381. // }
  382.  
  383. //THe IDE suck at detecting the type of the container in traverse so we hint, still valid code that compiles without it tho.
  384. v.grouped(n).toVector.traverse[Future, B] { x =>
  385. Future(
  386. x.foldMap(f)
  387. )
  388. }.map(_.combineAll)
  389. }
  390.  
  391. def main(args: Array[String]): Unit = {
  392. println {
  393. foldMap(Vector(1, 2, 3))(x => x.toString + "! ")
  394. }
  395. println {
  396. Await.result(parallelFoldMap((1 to 10000).toVector)(x => x * 2), 3.seconds)
  397. }
  398.  
  399. println {
  400. foldMap("Hello world!".toVector)(_.toString.toUpperCase)
  401. }
  402.  
  403. println {
  404. Await.result(parallelFoldMap("Hello world!".toVector)(_.toString.toUpperCase), 3.seconds)
  405. }
  406. }
  407. }
  408.  
  409. object DataValidationStudy {
  410.  
  411. final case class User(username: String, email: String)
  412.  
  413. object User {
  414. def create(username: String, email: String): Validated[Errors, User] = {
  415. (checkUsername(username).toValidated |@| checkEmail(email).toValidated).map(User.apply)
  416. }
  417. }
  418.  
  419. def main(args: Array[String]): Unit = {
  420. println(User.create("Noel1", "noel@underscore.io"))
  421. println(User.create("", "dave@underscore@io"))
  422. }
  423.  
  424. def checkUsername: Check[String, String] = {
  425. import StringValidators._
  426. check((longerThan(4) and alphanumeric).run)
  427. }
  428.  
  429.  
  430. def checkEmail: Check[String, String] = {
  431. import StringValidators._
  432.  
  433. def split: Check[String, (String, String)] = {
  434. check(_.split('@') match {
  435. case Array(first, second) =>
  436. Right((first, second))
  437. case other =>
  438. Left(error("Must contain single @ character"))
  439. })
  440. }
  441.  
  442. def join: Check[(String, String), String] = {
  443. check { case (l, r) => (checkLeft(l) |@| checkRight(r)).map(_ + "@" + _) }
  444. }
  445.  
  446. def checkLeft: Check[String, String] = checkPred(longerThan(0))
  447.  
  448. def checkRight: Check[String, String] = checkPred(longerThan(3) and contains('.'))
  449.  
  450. split andThen join
  451. }
  452.  
  453.  
  454. def error(s: String) = NonEmptyList(s, Nil)
  455.  
  456. object StringValidators {
  457. def longerThan(n: Int): Predicate[Errors, String] = {
  458. Predicate.lift(error(s"String must be longer than $n"), _.length > n)
  459. }
  460.  
  461. def alphanumeric: Predicate[Errors, String] = {
  462. Predicate.lift(error("String must be alpha numeric"), str => str.forall(_.isLetterOrDigit))
  463. }
  464.  
  465. def contains(c: Char): Predicate[Errors, String] = {
  466. Predicate.lift(error(s"String must contain char $c"), _.contains(c))
  467. }
  468.  
  469. def containsOnce(c: Char): Predicate[Errors, String] = {
  470. Predicate.lift(error(s"String must contain char $c only once"), i => i.filter(_ == c).length == 1)
  471. }
  472.  
  473. }
  474.  
  475.  
  476. sealed trait Predicate[E, A] {
  477.  
  478. import Predicate._
  479.  
  480. def apply(value: A)(implicit s: Semigroup[E]): Validated[E, A] = {
  481. this match {
  482. case Pure(f) => f(value)
  483. case And(left, right) =>
  484. val m = left(value) |@| right(value)
  485. m.map((_, _) => value)
  486. case Or(left, right) =>
  487. left(value) match {
  488. case Valid(v) => Valid(v)
  489. case Invalid(e) =>
  490. right(value) match {
  491. case Valid(v) => Valid(v)
  492. case Invalid(e2) => Invalid(e |+| e2)
  493. }
  494. }
  495. }
  496. }
  497.  
  498. def run(implicit s: Semigroup[E]): A => Either[E, A] = {
  499. a => this.apply(a).toEither
  500. }
  501.  
  502. def and(that: Predicate[E, A]): Predicate[E, A] = {
  503. And(this, that)
  504. }
  505.  
  506. def or(that: Predicate[E, A]): Predicate[E, A] = {
  507. Or(this, that)
  508. }
  509. }
  510.  
  511. object Predicate {
  512. def apply[E, A](f: A => Validated[E, A]): Predicate[E, A] = Pure(f)
  513.  
  514. def lift[E, A](e: E, f: A => Boolean): Predicate[E, A] = {
  515. Pure { a => if (f(a)) a.valid else e.invalid }
  516. }
  517.  
  518. final case class And[E, A](left: Predicate[E, A], right: Predicate[E, A]) extends Predicate[E, A]
  519.  
  520. final case class Or[E, A](left: Predicate[E, A], right: Predicate[E, A]) extends Predicate[E, A]
  521.  
  522. final case class Pure[E, A](func: A => Validated[E, A]) extends Predicate[E, A]
  523.  
  524. }
  525.  
  526. type Errors = NonEmptyList[String]
  527.  
  528. type Result[A] = Either[Errors, A]
  529.  
  530. type Check[A, B] = Kleisli[Result, A, B]
  531.  
  532. def check[A, B](func: A => Result[B]): Check[A, B] = {
  533. Kleisli(func)
  534. }
  535.  
  536. def checkPred[A](pred: Predicate[Errors, A]): Check[A, A] =
  537. Kleisli[Result, A, A](pred.run)
  538.  
  539. // sealed trait Check[E, A, B] {
  540. // def apply(a: A): Validated[E, B]
  541. //
  542. // def map[C](func: B => C): Check[E, A, C] = {
  543. // Check.Map(this, func)
  544. // }
  545. //
  546. // def flatMap[C](func: B => Check[E, A, C]): Check[E, A, C] = {
  547. // Check.FlatMap(this, func)
  548. // }
  549. //
  550. // def andThen[C](c: Check[E, B, C]): Check[E, A, C] = {
  551. // Check.AndThen(this, c)
  552. // }
  553. // }
  554.  
  555. // object Check {
  556. //
  557. // final case class Map[E, A, B, C](c: Check[E, A, B], f: B => C) extends Check[E, A, C] {
  558. // override def apply(a: A): Validated[E, C] = {
  559. // c(a).map(f)
  560. // }
  561. // }
  562. //
  563. // final case class AndThen[E, A, B, C](c1: Check[E, A, B], c2: Check[E, B, C]) extends Check[E, A, C] {
  564. // override def apply(a: A): Validated[E, C] = {
  565. // c1(a) match {
  566. // case Valid(v) => c2(v)
  567. // case e: Invalid[E] => e
  568. // }
  569. // }
  570. // }
  571. //
  572. // final case class FlatMap[E, A, B, C](c: Check[E, A, B], f: B => Check[E, A, C]) extends Check[E, A, C] {
  573. // override def apply(a: A): Validated[E, C] = {
  574. // c(a) match {
  575. // case Valid(v) => f(v)(a)
  576. // case e: Invalid[E] => e
  577. // }
  578. // }
  579. // }
  580. //
  581. // final case class Pure[E, A, B](f: A => Validated[E, B]) extends Check[E, A, B] {
  582. // override def apply(a: A): Validated[E, B] = f(a)
  583. // }
  584. //
  585. // final case class PurePredicate[E: Semigroup, A](p: Predicate[E, A]) extends Check[E, A, A] {
  586. // override def apply(a: A): Validated[E, A] = p(a)
  587. // }
  588. //
  589. // def apply[E: Semigroup, A](p: Predicate[E, A]): Check[E, A, A] = {
  590. // PurePredicate(p)
  591. // }
  592. //
  593. // def apply[E: Semigroup, A, B](f: A => Validated[E, B]): Check[E, A, B] = {
  594. // Pure(f)
  595. // }
  596. // }
  597. }
  598.  
  599. // Commutative Replicated Datatypes
  600. object CrdtStudy {
  601.  
  602. // final case class GCounter[A](counters: Map[String, A]) {
  603. // def increment(machine: String, amount: A)(implicit m: Monoid[A]): GCounter[A] = {
  604. // val c = counters.getOrElse(machine, m.empty) |+| amount
  605. // copy(counters + (machine -> c))
  606. // }
  607. //
  608. // def get: A = {
  609. // counters.foldMap(identity)
  610. // }
  611. //
  612. // def merge(that: GCounter[A])(implicit b: BoundedSemiLattice[A]): GCounter[A] = {
  613. // GCounter(this.counters |+| that.counters)
  614. // }
  615. //
  616. // }
  617. trait GCounter[F[_, _], K, V] {
  618. def increment(f: F[K, V])(machine: K, amount: V)(implicit m: Monoid[V]): F[K, V]
  619.  
  620. def total(f: F[K, V])(implicit m: Monoid[V]): V
  621.  
  622. def merge(f: F[K, V], that: F[K, V])(implicit m: BoundedSemiLattice[V]): F[K, V]
  623. }
  624.  
  625. object GCounter {
  626. def apply[F[_, _], K, V](implicit g: GCounter[F, K, V]): GCounter[F, K, V] = g
  627.  
  628. implicit class GCounterOps[F[_, _], K, V](f: F[K, V]) {
  629. def increment(key: K, value: V)(implicit g: GCounter[F, K, V], m: Monoid[V]): F[K, V] =
  630. g.increment(f)(key, value)
  631.  
  632. def total(implicit g: GCounter[F, K, V], m: Monoid[V]): V =
  633. g.total(f)
  634.  
  635. def merge(that: F[K, V])(implicit g: GCounter[F, K, V], b: BoundedSemiLattice[V]): F[K, V] =
  636. g.merge(f, that)
  637. }
  638.  
  639. implicit def keyValueInstance[F[_, _], K, V](implicit k: KeyValueStore[F], km: Monoid[F[K, V]], kf: Foldable[({type l[A] = F[K, A]})#l]): GCounter[F, K, V] =
  640. new GCounter[F, K, V] {
  641.  
  642. import KeyValueStore._ // For KeyValueStore syntax
  643.  
  644. def increment(f: F[K, V])(key: K, value: V)(implicit m: Monoid[V]): F[K, V] =
  645. f + (key, (f.getOrElse(key, m.empty) |+| value))
  646.  
  647. def total(f: F[K, V])(implicit m: Monoid[V]): V =
  648. f.foldMap(identity _)
  649.  
  650. def merge(f1: F[K, V], f2: F[K, V])(implicit b: BoundedSemiLattice[V]): F[K, V] =
  651. f1 |+| f2
  652. }
  653. }
  654.  
  655.  
  656. trait KeyValueStore[F[_, _]] {
  657. def +[K, V](f: F[K, V])(key: K, value: V): F[K, V]
  658.  
  659. def get[K, V](f: F[K, V])(key: K): Option[V]
  660.  
  661. def getOrElse[K, V](f: F[K, V])(key: K, or: V): V =
  662. get(f)(key).getOrElse(or)
  663. }
  664.  
  665. object KeyValueStore {
  666.  
  667. implicit class KeyValueStoreOps[F[_, _], K, V](f: F[K, V]) {
  668. def +(key: K, value: V)(implicit s: KeyValueStore[F]): F[K, V] = s.+(f)(key, value)
  669.  
  670. def get(key: K)(implicit s: KeyValueStore[F]): Option[V] = s.get(f)(key)
  671.  
  672. def getOrElse(key: K, or: V)(implicit s: KeyValueStore[F]): V = s.getOrElse(f)(key, or)
  673. }
  674.  
  675. implicit object mapKVStore extends KeyValueStore[Map] {
  676. override def +[K, V](f: Map[K, V])(key: K, value: V): Map[K, V] = f + (key -> value)
  677.  
  678. override def get[K, V](f: Map[K, V])(key: K): Option[V] = f.get(key)
  679. }
  680.  
  681. }
  682.  
  683. trait BoundedSemiLattice[A] extends Monoid[A] {
  684. def combine(a1: A, a2: A): A
  685.  
  686. def empty: A
  687. }
  688.  
  689. implicit val intLattice: BoundedSemiLattice[Int] = new BoundedSemiLattice[Int] {
  690. override def combine(a1: Int, a2: Int): Int = a1 max a2
  691.  
  692. override def empty: Int = 0
  693. }
  694.  
  695. implicit def latticeForSets[A]: BoundedSemiLattice[Set[A]] = new BoundedSemiLattice[Set[A]] {
  696. override def combine(a1: Set[A], a2: Set[A]): Set[A] = a1 union a2
  697.  
  698. override def empty: Set[A] = Set.empty[A]
  699. }
  700. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement