diff --git a/.travis.yml b/.travis.yml index b6c329b..08e3693 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ jdk: - openjdk8 script: - - sbt ";+check ;+cpl ;+lint ;+doc ;+test" + - sbt ";+check ;+cpl ;+test" - if [ -z "$TRAVIS_PULL_REQUEST" ] && [ "${TRAVIS_REPO_SLUG}" == "scalaz/ioeffect" ] ; then sbt publish ; fi before_cache: diff --git a/ioeffect/src/main/scala/scalaz/ioeffect/IO.scala b/ioeffect/src/main/scala/scalaz/ioeffect/IO.scala index 2810b45..6f15e60 100644 --- a/ioeffect/src/main/scala/scalaz/ioeffect/IO.scala +++ b/ioeffect/src/main/scala/scalaz/ioeffect/IO.scala @@ -3,12 +3,11 @@ package scalaz.ioeffect import scala.annotation.switch import scala.concurrent.duration._ -import scalaz.{ -\/, @@, \/, \/-, unused, Maybe } +import scalaz.{ -\/, \/, \/-, unused, Maybe } import scalaz.syntax.either._ import scalaz.ioeffect.Errors._ import scalaz.ioeffect.Errors.TerminatedException import scalaz.Liskov.<~< -import scalaz.Tags.Parallel import scala.concurrent.{ ExecutionContext, Future } @@ -214,6 +213,12 @@ sealed abstract class IO[E, A] { self => case _ => new IO.Attempt(self) } + /** + * Ignores the error and value of this IO, useful for explicitly acknowledging + * that a cleanup task will have its result ignored. + */ + def ignore: IO[Void, Unit] = attempt[Void].toUnit + /** * When this action represents acquisition of a resource (for example, * opening a file, launching a thread, etc.), `bracket` can be used to ensure @@ -520,8 +525,6 @@ sealed abstract class IO[E, A] { self => } object IO extends IOInstances { - type Par[e, a] = IO[e, a] @@ Parallel - final object Tags { final val FlatMap = 0 final val Point = 1 @@ -689,11 +692,6 @@ object IO extends IOInstances { */ final def sync[E, A](effect: => A): IO[E, A] = new SyncEffect(() => effect) - /** - * To ease migration. - */ - final def apply[E, A](effect: => A): IO[E, A] = sync(effect) - /** * * Imports a synchronous effect into a pure `IO` value, translating any @@ -704,8 +702,13 @@ object IO extends IOInstances { * }}} */ final def syncThrowable[A](effect: => A): IO[Throwable, A] = - syncCatch(effect) { - case t: Throwable => t + IO.suspend { + try { + val a = effect + IO.sync(a) + } catch { + case t: Throwable => IO.fail(t) + } } /** diff --git a/ioeffect/src/main/scala/scalaz/ioeffect/IOInstances.scala b/ioeffect/src/main/scala/scalaz/ioeffect/IOInstances.scala index 76e5b0a..c99c302 100644 --- a/ioeffect/src/main/scala/scalaz/ioeffect/IOInstances.scala +++ b/ioeffect/src/main/scala/scalaz/ioeffect/IOInstances.scala @@ -2,19 +2,21 @@ package scalaz package ioeffect +import Tags.Parallel + abstract class IOInstances extends IOInstances1 { // cached for efficiency implicit val taskInstances: MonadError[Task, Throwable] with BindRec[Task] with Plus[Task] = new IOMonadError[Throwable] with IOPlus[Throwable] - implicit val taskParAp: Applicative[Task.Par] = new IOParApplicative[Throwable] + implicit val taskParAp: Applicative[λ[α => Task[α] @@ Parallel]] = new IOParApplicative[Throwable] } sealed abstract class IOInstances1 extends IOInstance2 { implicit def ioInstances[E]: MonadError[IO[E, ?], E] with BindRec[IO[E, ?]] with Bifunctor[IO] with Plus[IO[E, ?]] = new IOMonadError[E] with IOPlus[E] with IOBifunctor - implicit def ioParAp[E]: Applicative[IO.Par[E, ?]] = new IOParApplicative[E] + implicit def ioParAp[E]: Applicative[λ[α => IO[E, α] @@ Parallel]] = new IOParApplicative[E] } sealed abstract class IOInstance2 { @@ -49,19 +51,21 @@ private trait IOBifunctor extends Bifunctor[IO] { IO.absolve(fab.attempt.map(_.bimap(f, g))) } -private class IOParApplicative[E] extends Applicative[IO.Par[E, ?]] { - override def point[A](a: => A): IO.Par[E, A] = Tag(IO.point(a)) - override def ap[A, B](fa: => IO.Par[E, A])(f: => IO.Par[E, A => B]): IO.Par[E, B] = { +private class IOParApplicative[E] extends Applicative[λ[α => IO[E, α] @@ Parallel]] { + type Par[α] = IO[E, α] @@ Parallel + + override def point[A](a: => A): Par[A] = Tag(IO.point(a)) + override def ap[A, B](fa: => Par[A])(f: => Par[A => B]): Par[B] = { lazy val fa0: IO[E, A] = Tag.unwrap(fa) Tag(Tag.unwrap(f).flatMap(x => fa0.map(x))) } - override def map[A, B](fa: IO.Par[E, A])(f: A => B): IO.Par[E, B] = + override def map[A, B](fa: Par[A])(f: A => B): Par[B] = Tag(Tag.unwrap(fa).map(f)) override def apply2[A, B, C]( - fa: => IO.Par[E, A], - fb: => IO.Par[E, B] - )(f: (A, B) => C): IO.Par[E, C] = + fa: => Par[A], + fb: => Par[B] + )(f: (A, B) => C): Par[C] = Tag(Tag.unwrap(fa).par(Tag.unwrap(fb)).map(f.tupled)) } diff --git a/ioeffect/src/main/scala/scalaz/ioeffect/package.scala b/ioeffect/src/main/scala/scalaz/ioeffect/package.scala index 7747941..6a8185e 100644 --- a/ioeffect/src/main/scala/scalaz/ioeffect/package.scala +++ b/ioeffect/src/main/scala/scalaz/ioeffect/package.scala @@ -5,8 +5,6 @@ package scalaz import scala.concurrent.{ ExecutionContext, Future } import scala.concurrent.duration.Duration -import scalaz.Tags.Parallel - package object ioeffect { implicit class IOVoidSyntax[A](val io: IO[Void, A]) extends AnyRef { @@ -15,11 +13,10 @@ package object ioeffect { type Task[A] = IO[Throwable, A] object Task { - type Par[a] = Task[a] @@ Parallel + final def apply[A](effect: => A): Task[A] = IO.syncThrowable(effect) final def now[A](effect: A): Task[A] = IO.now(effect) final def point[A](effect: => A): Task[A] = IO.point(effect) - final def apply[A](effect: => A): Task[A] = IO.apply(effect) final def sync[A](effect: => A): Task[A] = IO.sync(effect) final def async[A](register: (ExitResult[Throwable, A] => Unit) => Unit): Task[A] = IO.async(register) diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index b6963df..42410ec 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -16,7 +16,7 @@ object ProjectKeys { def SemanticDB = addCompilerPlugin( - ("org.scalameta" % "semanticdb-scalac" % "4.0.0-M3").cross(CrossVersion.full) + ("org.scalameta" % "semanticdb-scalac" % "4.0.0-M4").cross(CrossVersion.full) ) private val silencerVersion = "0.6" @@ -71,9 +71,9 @@ object ProjectPlugin extends AutoPlugin { testFrameworks in Test := Seq(TestFrameworks.Specs2, TestFrameworks.ScalaCheck, TestFrameworks.ScalaTest), MonadicFor, KindProjector, - SemanticDB, + //SemanticDB, // disabling scalafix until 0.6 stabilises scalacOptions ++= Seq( - "-Yrangepos", // needed by semanticdb + //"-Yrangepos", // needed by semanticdb "-unchecked", "-explaintypes", "-Ypartial-unification",