Browse Source

Switch from Scalaz to Cats

master
Sarah Gerweck 6 years ago
parent
commit
c1fafcfc8f
No known key found for this signature in database GPG Key ID: AFCB37207DB3F226
  1. 6
      CHANGELOG.md
  2. 2
      build.sbt
  3. 4
      project/Dependencies.scala
  4. 1
      project/ProjectSettings.scala
  5. 47
      src/main/scala/org/gerweck/scalafx/util/observable.scala
  6. 2
      src/main/scala/org/gerweck/scalafx/util/package.scala

6
CHANGELOG.md

@ -84,3 +84,9 @@ change.
* Update Shapeless to 2.3.3
* Update Scalaz to 7.2.18
* 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.

2
build.sbt

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

4
project/Dependencies.scala

@ -24,7 +24,7 @@ object Dependencies {
final val scalaParserVersion = "1.0.4"
final val scalaXmlVersion = "1.0.5"
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 scallopVersion = "1.0.1"
@ -39,7 +39,7 @@ object Dependencies {
val gerweckUtil = "org.gerweck.scala" %% "gerweck-utils" % gerweckUtilVersion
val gerweckUtilAkka = "org.gerweck.scala" %% "gerweck-utils-akka" % gerweckUtilVersion
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 scallop = "org.rogach" %% "scallop" % scallopVersion

1
project/ProjectSettings.scala

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

47
src/main/scala/org/gerweck/scalafx/util/observable.scala

@ -2,7 +2,7 @@ package org.gerweck.scalafx.util
import language.implicitConversions
import scalaz._
import cats._
import scalafx.beans.property._
import scalafx.beans.value._
@ -16,7 +16,7 @@ trait ObservableImplicits {
* a property in a tight loop, I expect you'll have bigger performance
* 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. */
override def map[A, B](a: Observable[A])(f: A => B): ReadOnlyObjectProperty[B] = {
@inline def recalculate(): B = f(a.value)
@ -38,12 +38,12 @@ trait ObservableImplicits {
prop
}
def point[A](a: => A): ReadOnlyObjectProperty[A] = {
override def pure[A](a: A): ReadOnlyObjectProperty[A] = {
ObjectProperty[A](a)
}
/* 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)
val originalValue = recalculate()
@ -66,13 +66,18 @@ trait ObservableImplicits {
prop
}
/* Aka `flatMap` */
override def bind[A, B](fa: Observable[A])(f: A => Observable[B]): ReadOnlyObjectProperty[B] = {
join(map(fa)(f))
override def flatMap[A, B](fa: Observable[A])(f: A => Observable[B]): ReadOnlyObjectProperty[B] = {
flatten(map(fa)(f))
}
/* Aka `flatten` */
override def join[A](ooa: Observable[Observable[A]]): ReadOnlyObjectProperty[A] = {
override def tailRecM[A, B](a: A)(f: A => Observable[Either[A, B]]): Observable[B] = {
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 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 point[A](a: => A): ReadOnlyObjectProperty[A] = observableInstances.point(a)
override def ap[A, B](fa: => ReadOnlyObjectProperty[A])(f: => ReadOnlyObjectProperty[A => B]): ReadOnlyObjectProperty[B] = observableInstances.ap(fa)(f)
override def bind[A, B](fa: ReadOnlyObjectProperty[A])(f: A => ReadOnlyObjectProperty[B]): ReadOnlyObjectProperty[B] = observableInstances.bind(fa)(f)
override def join[A](ooa: ReadOnlyObjectProperty[ReadOnlyObjectProperty[A]]): ReadOnlyObjectProperty[A] = {
override def pure[A](a: A): ReadOnlyObjectProperty[A] = observableInstances.pure(a)
override def ap[A, B](f: ReadOnlyObjectProperty[A => B])(fa: ReadOnlyObjectProperty[A]): ReadOnlyObjectProperty[B] = observableInstances.ap(f)(fa)
override def flatMap[A, B](fa: ReadOnlyObjectProperty[A])(f: A => ReadOnlyObjectProperty[B]): ReadOnlyObjectProperty[B] = observableInstances.flatMap(fa)(f)
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. */
@inline def oa() = ooa.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
def map[B](f: A => B) = oapp.map(self)(f)
def flatMap[B](f: A => Observable[B]) = oapp.bind(self)(f)
def <*>[B](f: Observable[A => B]): ObservableValue[B, B] = oapp.ap(self)(f)
def flatMap[B](f: A => Observable[B]) = oapp.flatMap(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)
final def *>[B](fb: ObjObs[B]): Observable[B] = oapp.apply2(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[B] = oapp.map2(self,fb)((_,b) => b)
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)

2
src/main/scala/org/gerweck/scalafx/util/package.scala

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

Loading…
Cancel
Save