Switch from Scalaz to Cats

This commit is contained in:
Sarah Gerweck 2018-01-10 21:32:08 -08:00
parent 29632786b3
commit c1fafcfc8f
No known key found for this signature in database
GPG Key ID: AFCB37207DB3F226
6 changed files with 39 additions and 23 deletions

View File

@ -84,3 +84,9 @@ change.
* Update Shapeless to 2.3.3 * Update Shapeless to 2.3.3
* Update Scalaz to 7.2.18 * Update Scalaz to 7.2.18
* Update Gerweck Utils to 2.7.2 * Update Gerweck Utils to 2.7.2
### 0.14
* Migration from Scalaz to Cats
* This is the library we use to provide `Monad` and `Applicative` instances
for observable values.

View File

@ -19,7 +19,7 @@ lazy val root = (project in file ("."))
gerweckUtil, gerweckUtil,
scalaJava8, scalaJava8,
scalaFx, scalaFx,
scalaz, cats,
shapeless shapeless
), ),

View File

@ -24,7 +24,7 @@ object Dependencies {
final val scalaParserVersion = "1.0.4" final val scalaParserVersion = "1.0.4"
final val scalaXmlVersion = "1.0.5" final val scalaXmlVersion = "1.0.5"
final val gerweckUtilVersion = "2.7.2" final val gerweckUtilVersion = "2.7.2"
final val scalazVersion = "7.2.18" final val catsVersion = "1.0.1"
final val shapelessVersion = "2.3.3" final val shapelessVersion = "2.3.3"
final val scallopVersion = "1.0.1" final val scallopVersion = "1.0.1"
@ -39,7 +39,7 @@ object Dependencies {
val gerweckUtil = "org.gerweck.scala" %% "gerweck-utils" % gerweckUtilVersion val gerweckUtil = "org.gerweck.scala" %% "gerweck-utils" % gerweckUtilVersion
val gerweckUtilAkka = "org.gerweck.scala" %% "gerweck-utils-akka" % gerweckUtilVersion val gerweckUtilAkka = "org.gerweck.scala" %% "gerweck-utils-akka" % gerweckUtilVersion
val scalaJava8 = "org.scala-lang.modules" %% "scala-java8-compat" % scalaJava8Version val scalaJava8 = "org.scala-lang.modules" %% "scala-java8-compat" % scalaJava8Version
val scalaz = "org.scalaz" %% "scalaz-core" % scalazVersion val cats = "org.typelevel" %% "cats-core" % catsVersion
val shapeless = "com.chuusai" %% "shapeless" % shapelessVersion val shapeless = "com.chuusai" %% "shapeless" % shapelessVersion
val scallop = "org.rogach" %% "scallop" % scallopVersion val scallop = "org.rogach" %% "scallop" % scallopVersion

View File

@ -15,6 +15,7 @@ trait ProjectSettings
override final val extraScalaVersions = Seq("2.11.11") override final val extraScalaVersions = Seq("2.11.11")
override final val defaultOptimize = true override final val defaultOptimize = true
override final val defaultOptimizeGlobal = false override final val defaultOptimizeGlobal = false
override final val extraScalacOptions = Seq("-Ypartial-unification")
override final val sonatypeResolver = true override final val sonatypeResolver = true

View File

@ -2,7 +2,7 @@ package org.gerweck.scalafx.util
import language.implicitConversions import language.implicitConversions
import scalaz._ import cats._
import scalafx.beans.property._ import scalafx.beans.property._
import scalafx.beans.value._ import scalafx.beans.value._
@ -16,7 +16,7 @@ trait ObservableImplicits {
* a property in a tight loop, I expect you'll have bigger performance * a property in a tight loop, I expect you'll have bigger performance
* issues.) * issues.)
*/ */
implicit val observableInstances = new Applicative[Observable] with Functor[Observable] with Monad[Observable] { implicit object observableInstances extends Applicative[Observable] with Functor[Observable] with Monad[Observable] {
/* Map can be derived from `ap`, but this adds less overhead. */ /* Map can be derived from `ap`, but this adds less overhead. */
override def map[A, B](a: Observable[A])(f: A => B): ReadOnlyObjectProperty[B] = { override def map[A, B](a: Observable[A])(f: A => B): ReadOnlyObjectProperty[B] = {
@inline def recalculate(): B = f(a.value) @inline def recalculate(): B = f(a.value)
@ -38,12 +38,12 @@ trait ObservableImplicits {
prop prop
} }
def point[A](a: => A): ReadOnlyObjectProperty[A] = { override def pure[A](a: A): ReadOnlyObjectProperty[A] = {
ObjectProperty[A](a) ObjectProperty[A](a)
} }
/* Ap can be derived from `point` and `bind`, but this has less overhead. */ /* Ap can be derived from `point` and `bind`, but this has less overhead. */
override def ap[A, B](fa: => Observable[A])(f: => Observable[A => B]): ReadOnlyObjectProperty[B] = { override def ap[A, B](f: Observable[A => B])(fa: Observable[A]): ReadOnlyObjectProperty[B] = {
@inline def recalculate(): B = (f.value)(fa.value) @inline def recalculate(): B = (f.value)(fa.value)
val originalValue = recalculate() val originalValue = recalculate()
@ -66,13 +66,18 @@ trait ObservableImplicits {
prop prop
} }
/* Aka `flatMap` */ override def flatMap[A, B](fa: Observable[A])(f: A => Observable[B]): ReadOnlyObjectProperty[B] = {
override def bind[A, B](fa: Observable[A])(f: A => Observable[B]): ReadOnlyObjectProperty[B] = { flatten(map(fa)(f))
join(map(fa)(f))
} }
/* Aka `flatten` */ override def tailRecM[A, B](a: A)(f: A => Observable[Either[A, B]]): Observable[B] = {
override def join[A](ooa: Observable[Observable[A]]): ReadOnlyObjectProperty[A] = { this.flatMap(f(a)) {
case Right(b) => pure(b)
case Left(nextA) => tailRecM(nextA)(f)
}
}
override def flatten[A](ooa: Observable[Observable[A]]): ReadOnlyObjectProperty[A] = {
@inline def oa() = ooa.value @inline def oa() = ooa.value
@inline def calc(): A = oa().value @inline def calc(): A = oa().value
@ -109,12 +114,18 @@ trait ObservableImplicits {
} }
} }
implicit val readOnlyObjectPropertyInstances = new Applicative[ReadOnlyObjectProperty] with Functor[ReadOnlyObjectProperty] with Monad[ReadOnlyObjectProperty] { implicit object readOnlyObjectPropertyInstances extends Applicative[ReadOnlyObjectProperty] with Functor[ReadOnlyObjectProperty] with Monad[ReadOnlyObjectProperty] {
override def map[A, B](a: ReadOnlyObjectProperty[A])(f: A => B): ReadOnlyObjectProperty[B] = observableInstances.map(a)(f) override def map[A, B](a: ReadOnlyObjectProperty[A])(f: A => B): ReadOnlyObjectProperty[B] = observableInstances.map(a)(f)
override def point[A](a: => A): ReadOnlyObjectProperty[A] = observableInstances.point(a) override def pure[A](a: A): ReadOnlyObjectProperty[A] = observableInstances.pure(a)
override def ap[A, B](fa: => ReadOnlyObjectProperty[A])(f: => ReadOnlyObjectProperty[A => B]): ReadOnlyObjectProperty[B] = observableInstances.ap(fa)(f) override def ap[A, B](f: ReadOnlyObjectProperty[A => B])(fa: ReadOnlyObjectProperty[A]): ReadOnlyObjectProperty[B] = observableInstances.ap(f)(fa)
override def bind[A, B](fa: ReadOnlyObjectProperty[A])(f: A => ReadOnlyObjectProperty[B]): ReadOnlyObjectProperty[B] = observableInstances.bind(fa)(f) override def flatMap[A, B](fa: ReadOnlyObjectProperty[A])(f: A => ReadOnlyObjectProperty[B]): ReadOnlyObjectProperty[B] = observableInstances.flatMap(fa)(f)
override def join[A](ooa: ReadOnlyObjectProperty[ReadOnlyObjectProperty[A]]): ReadOnlyObjectProperty[A] = { override def tailRecM[A, B](a: A)(f: A => ReadOnlyObjectProperty[Either[A, B]]): ReadOnlyObjectProperty[B] = {
flatMap(f(a)) {
case Right(b) => pure(b)
case Left(nextA) => tailRecM(nextA)(f)
}
}
override def flatten[A](ooa: ReadOnlyObjectProperty[ReadOnlyObjectProperty[A]]): ReadOnlyObjectProperty[A] = {
/* NOTE: this is copy-pasted from `observableInstances`. TBD: Find a way to share this. */ /* NOTE: this is copy-pasted from `observableInstances`. TBD: Find a way to share this. */
@inline def oa() = ooa.value @inline def oa() = ooa.value
@inline def calc(): A = oa().value @inline def calc(): A = oa().value
@ -197,11 +208,11 @@ final class RichObservable[A, C](val self: ObservableValue[A, C]) extends AnyVal
@inline private def oapp = observableInstances @inline private def oapp = observableInstances
def map[B](f: A => B) = oapp.map(self)(f) def map[B](f: A => B) = oapp.map(self)(f)
def flatMap[B](f: A => Observable[B]) = oapp.bind(self)(f) def flatMap[B](f: A => Observable[B]) = oapp.flatMap(self)(f)
def <*>[B](f: Observable[A => B]): ObservableValue[B, B] = oapp.ap(self)(f) def <*>[B](f: Observable[A => B]): ObservableValue[B, B] = oapp.ap(f)(self)
def tuple[B](f: Observable[B]): Observable[(A,B)] = oapp.tuple2(self, f) def tuple[B](f: Observable[B]): Observable[(A,B)] = oapp.tuple2(self, f)
final def *>[B](fb: ObjObs[B]): Observable[B] = oapp.apply2(self,fb)((_,b) => b) final def *>[B](fb: ObjObs[B]): Observable[B] = oapp.map2(self,fb)((_,b) => b)
final def <*[B](fb: ObjObs[B]): Observable[A] = oapp.apply2(self,fb)((a,_) => a) final def <*[B](fb: ObjObs[B]): Observable[A] = oapp.map2(self,fb)((a,_) => a)
final def |@|[B, B1](fb: ObservableValue[B, B1]) = ObservableTupler(self, fb) final def |@|[B, B1](fb: ObservableValue[B, B1]) = ObservableTupler(self, fb)

View File

@ -8,8 +8,6 @@ import scalafx.scene.input._
import scalafx.scene.layout.GridPane import scalafx.scene.layout.GridPane
import scalafx.scene.text.Text import scalafx.scene.text.Text
import scalaz._
/** Various implicits and global utilities for ScalaFX work. /** Various implicits and global utilities for ScalaFX work.
* *
* @author Sarah Gerweck <sarah@atscale.com> * @author Sarah Gerweck <sarah@atscale.com>