Code Monkey home page Code Monkey logo

ioeffect's Introduction

Scalaz

Scalaz is a Scala library for functional programming.

It provides purely functional data structures to complement those from the Scala standard library. It defines a set of foundational type classes (e.g. Functor, Monad) and corresponding instances for a large number of data structures.

IRC

Getting Scalaz

The current stable version is 7.3.8, which is cross-built against Scala 2.12.x, 2.13.x, 3.x and Scala.js, scala-native.

If you're using SBT, add the following line to your build file:

libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.3.8"

For Maven and other build tools, you can visit search.maven.org. (This search will also list all available modules of scalaz.)

To get sample configurations, click on the version of the module you are interested in. You can also find direct download links at the bottom of that page. Choose the file ending in 7.3.8.jar.

Quick Start

import scalaz._
import std.option._, std.list._ // functions and type class instances for Option and List

scala> Apply[Option].apply2(some(1), some(2))((a, b) => a + b)
res0: Option[Int] = Some(3)

scala> Traverse[List].traverse(List(1, 2, 3))(i => some(i))
res1: Option[List[Int]] = Some(List(1, 2, 3))

Use of the Ops classes, defined under scalaz.syntax.

import scalaz._
import std.list._ // type class instances for List
import syntax.bind._ // syntax for the Bind type class (and its parents)

scala> List(List(1)).join
res0: List[Int] = List(1)

scala> List(true, false).ifM(List(0, 1), List(2, 3))
res1: List[Int] = List(0, 1, 2, 3)

We've gone to great lengths to give you an a-la-carte importing experience, but if you prefer an all-you-can-eat buffet, you're in luck:

import scalaz._
import Scalaz._

scala> NonEmptyList(1, 2, 3).cojoin
res0: scalaz.NonEmptyList[scalaz.NonEmptyList[Int]] = NonEmptyList(NonEmptyList(1, 2, 3), NonEmptyList(2, 3), NonEmptyList(3))

scala> 1.node(2.leaf, 3.node(4.leaf))
res1: scalaz.Tree[Int] = <tree>

scala> List(some(1), none).suml
res2: Option[Int] = Some(1)

Resources

Let the types speak for themselves via the Scalaz Scaladocs!

The examples module contains some snippets of Scalaz usage.

The wiki contains release and migration information.

Talk with us by joining IRC: irc.libera.chat channel #scalaz, or join the Scalaz mailing list on Google Groups.

The typelevel blog has some great posts such as Towards Scalaz by Adelbert Chang.

Learning Scalaz is a great series of blog posts by Eugene Yokota. Thanks, Eugene!

Changes in Version 7

Scalaz 7 represents a major reorganization of the library. We have taken a fresh look at the challenges of encoding type classes in Scala, in particular at when and how to employ the implicit scope.

At a glance

  • scalaz.{effect, iteratee} split to separate sub-projects; scalaz.{http, geo} dropped.
  • Refined and expanded the type class hierarchy.
  • Type class instances are no longer defined in the companion objects of the type class. Instances for standard library types are defined under scalaz.std, and instances for Scalaz data types are defined in the companion object for those types. An instance definition can provide multiple type classes in a single place, which was not always possible in Scalaz 6.
  • Type class instances have been organized to avoid ambiguity, a problem that arises when instances are dependent on other instances (for example, Monoid[(A, B)])
  • Use of implicit views to provide access to Scalaz functionality as extension methods has been segregated to scalaz.syntax, and can be imported selectively, and need not be used at all.
  • Related functions are defined in the type class trait, to support standalone usage of the type class. In Scalaz 6, these were defined in Identity, MA, or MAB.
  • New data structures have been added, and existing ones generalized. A number of monad transformers have been provided, in some cases generalizing old data structures.

Modularity

Scalaz has been modularised.

  • scalaz-core: Type class hierarchy, data structures, type class instances for the Scala and Java standard libraries, implicit conversions / syntax to access these.
  • scalaz-effect: Data structures to represent and compose IO effects in the type system.
  • scalaz-iteratee: Experimental new Iteratee implementation

Type Class Hierarchy

  • Type classes form an inheritance hierarchy, as in Scalaz 6. This is convenient both at the call site and at the type class instance definition. At the call site, it ensures that you can call a method requiring a more general type class with an instance of a more specific type class:
def bar[M[_]: Functor] = ()

def foo[M[_]: Monad] = bar[M] // Monad[M] is a subtype of Functor[M]
  • The hierarchy itself is largely the same as in Scalaz 6. However, there have been a few adjustments, some method signatures have been adjusted to support better standalone usage, so code depending on these will need to be re-worked.

Type Class Instance Definition

  • Constructive implicits, which create a type class instance automatically based on instances of all parent type classes, are removed. These led to subtle errors with ambiguous implicits, such as this problem with FunctorBindApply
  • Type class instances are no longer declared in fragments in the companion objects of the type class. Instead, they are defined in the package scalaz.std, and must be imported. These instances are defined in traits which will be mixed together into an object for importing en-masse, if desired.
  • A single implicit can define a number of type class instances for a type.
  • A type class definition can override methods (including derived methods) for efficiency.

Here is an instance definition for Option. Notice that the method map has been overridden.

  implicit val option: Traverse[Option] with MonadPlus[Option] = new Traverse[Option] with MonadPlus[Option] {
    def point[A](a: => A) = Some(a)
    def bind[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa flatMap f
    override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa map f
    def traverseImpl[F[_], A, B](fa: Option[A])(f: A => F[B])(implicit F: Applicative[F]) =
      fa map (a => F.map(f(a))(Some(_): Option[B])) getOrElse F.point(None)
    def empty[A]: Option[A] = None
    def plus[A](a: Option[A], b: => Option[A]) = a orElse b
    def foldR[A, B](fa: Option[A], z: B)(f: (A) => (=> B) => B): B = fa match {
      case Some(a) => f(a)(z)
      case None => z
    }
  }

To use this, one would:

import scalaz.std.option.optionInstance
// or, importing all instances en-masse
// import scalaz.Scalaz._

val M = Monad[Option]
val oi: Option[Int] = M.point(0)

Syntax

We co-opt the term syntax to refer to the way we allow the functionality of Scalaz to be called in the object.method(args) form, which can be easier to read, and, given that type inference in Scala flows from left-to-right, can require fewer type annotations.

  • No more Identity, MA, or MAB from Scalaz 6.
  • Syntax is segregated from rest of the library, in a sub-package scalaz.syntax.
  • All Scalaz functionality is available without using the provided syntax, by directly calling methods on the type class or its companion object.
  • Syntax is available a-la-carte. You can import the syntax for working with particular type classes where you need it. This avoids flooding the autocompletion in your IDE with every possible extension method. This should also help compiler performance, by reducing the implicit search space.
  • Syntax is layered in the same way as type classes. Importing the syntax for, say, Applicative will also provide the syntax for Apply and Functor.

Syntax can be imported in two ways. Firstly, the syntax specialized for a particular instance of a type class can be imported directly from the instance itself.

// import the type class instance
import scalaz.std.option.optionInstance

// import the implicit conversions to `MonadOps[Option, A]`, `BindOps[Option, A]`, ...
import optionInstance.monadSyntax._

val oi: Option[Option[Int]] = Some(Some(1))

// Expands to: `ToBindOps(io).join`
oi.join

Alternatively, the syntax can be imported for a particular type class.

// import the type class instance
import scalaz.std.option.optionInstance

// import the implicit conversions to `MonadOps[F, A]`, `BindOps[F, A]`, ...
import scalaz.syntax.monad._

val oi: Option[Option[Int]] = Some(Some(1))

// Expands to: ToBindOps(io).join
oi.join

For some degree of backwards compatibility with Scalaz 6, the über-import of import scalaz.Scalaz._ will import all implicit conversions that provide syntax (as well as type class instances and other functions). However, we recommend to review usage of this and replace with more focussed imports.

Standalone Type Class Usage

Type classes should be directly usable, without first needing to trigger implicit conversions. This might be desirable to reduce the runtime or cognitive overhead of the pimped types, or to define your own pimped types with a syntax of your choosing.

  • The methods in type classes have been curried to maximize type inference.
  • Derived methods, based on the abstract methods in a type class, are defined in the type class itself.
  • Each type class companion object is fitted with a convenient apply method to obtain an instance of the type class.
    // Equivalent to `implicitly[Monad[Option]]`
    val O = Monad[Option]

    // `bind` is defined with two parameter sections, so that the type of `x` is inferred as `Int`.
    O.bind(Some(1))(x => Some(x * 2))

    def plus(a: Int, b: Int) = a + b

    // `Apply#lift2` is a function derived from `Apply#ap`.
    val plusOpt = O.lift2(plus)

Type Class Instance Dependencies

Type class instances may depend on other instances. In simple cases, this is as straightforward as adding an implicit parameter (or, equivalently, a context bound), to the implicit method.

  implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = new Monoid[Option[A]] {
    def append(f1: Option[A], f2: => Option[A]): Option[A] = (f1, f2) match {
      case (Some(a1), Some(a2)) => Some(Semigroup[A].append(a1, a2))
      case (Some(a1), None) => f1
      case (None, Some(a2)) => f2
      case (None, None) => None
    }

    def zero: Option[A] = None
  }

Type class instances for 'transformers', such as OptionT, present a more subtle challenge. OptionT[F, A] is a wrapper for a value of type F[Option[A]]. It allows us to write:

val ot = OptionT(List(Some(1), None))
ot.map((a: Int) => a * 2) // OptionT(List(Some(2), None))

The method OptionT#map requires an implicit parameter of type Functor[F], whereas OptionT#flatMap requires one of type Monad[F]. The capabilities of OptionT increase with those of F. We need to encode this into the type class instances for [a]OptionT[F[A]].

This is done with a hierarchy of type class implementation traits and a corresponding set of prioritized implicit methods.

In case of ambiguous implicits, Scala will favour one defined in a sub-class of the other. This is to avoid ambiguity when in cases like the following:

type OptionTList[A] = OptionT[List[A]]
implicitly[Functor[OptionTList]]

// Candidates:
// 1. OptionT.OptionTFunctor[List](implicitly[Functor[List]])
// 2. OptionT.OptionTMonad[List](implicitly[Functor[List]])
// #2 is defined in a subclass of the enclosing class of #1, so #2 is preferred.

Transformers and Identity

A stronger emphasis has been placed on transformer data structures (aka Monad Transformers). For example State is now a type alias for StateT[Id, A, B].

Id is defined in the scalaz package object as:

type Id[A] = A

Contributing

Documentation for contributors

Credits

Support for Scalaz development is provided by Jetbrains.

Thanks to Mark Harrah and the sbt contributors for providing our build tool.

ioeffect's People

Contributors

barambani avatar danielyli avatar edmundnoble avatar emilypi avatar fommil avatar jmcardon avatar ktonga avatar nequissimus avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ioeffect's Issues

Can't compile the main example

I can't compile the example code provided in the README.
I get the following compilation error:

[error] /MyApp.scala:10: overriding method run in trait SafeApp of type (args: List[String])scalaz.ioeffect.IO[scalaz.ioeffect.Void, MyApp.ExitStatus];
[error]  method run has incompatible type
[error]   def run(args: List[String]): IO[Void, ExitStatus] =
[error]       ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Feb 13, 2019 4:34:13 PM

And the following in IntelliJ:

Overriding type List[String] => IO[Void, MyApp.ExitStatus] does not conform to base type List[String] => IO[ioeffect.Void, SafeApp.this.ExitStatus]

Just to be clear, here is the example code from the README that I'm trying to run:

import scalaz.ioeffect.{IO, SafeApp}
import scalaz.ioeffect.console._

import java.io.IOException

object MyApp extends SafeApp {

  def run(args: List[String]): IO[Void, ExitStatus] =
    myAppLogic.attempt.map(_.fold(_ => 1, _ => 0)).map(ExitStatus.ExitNow(_))

  def myAppLogic: IO[IOException, Unit] =
    for {
      _ <- putStrLn("Hello! What is your name?")
      n <- getStrLn
      _ <- putStrLn("Hello, " + n + ", good to meet you!")
    } yield ()
}

I am using Scala 2.11.7 and Scalaz 7.2.27

SNAPSHOT instructions

rather that publish binaries, we should note that this is how to declare a source dependency

val ioeffect = ProjectRef(
  uri("git://github.com/scalaz/ioeffect.git#1a3b397"),
  "ioeffect"
)

and then .dependsOn(ioeffect) instead of libraryDependencies

scaladoc is empty

🤔 ?

$ wget https://oss.sonatype.org/content/repositories/releases/org/scalaz/scalaz-ioeffect_2.12/2.0.0/scalaz-ioeffect_2.12-2.0.0-javadoc.jar
$ unzip -Z scalaz-ioeffect_2.12-2.0.0-javadoc.jar 
Archive:  scalaz-ioeffect_2.12-2.0.0-javadoc.jar
Zip file size: 189 bytes, number of entries: 1
-rw----     2.0 fat       25 bX defN 18-Apr-20 23:16 META-INF/MANIFEST.MF
1 file, 25 bytes uncompressed, 27 bytes compressed:  -8.0%

MonadPlus instance seems wrong

I think we can only provide MonadPlus when E is Unit. Otherwise we can't differentiate between failures and the empty failure, or maybe our Plus logic needs to be more advanced.

Fiber compositions does not return any value

Sorry about open here this issue, but to be honest there's no community mature enough in StackOverFlow to help on issues related with this library.

I'm trying to do an example of composition of Fibers, based in the for comprehension that you provide with fibboinachi example

I manage to make it work the fibbonachi, but if you execute this one is not returning anything.
most probably it will be something silly so sorry in advance XD!

@Test
def compositionOfFibersFeature(): Unit = {
  println(s"Before ${Thread.currentThread().getName}")
  def composition: IO[Throwable, String] = for {
    fiber <- createIO("Business logic 1").fork
    fiber1 <- createIO("Business logic 2").fork
    v2 <- fiber1.join
    v1 <- fiber.join
  } yield v1 + v2
  println(s"After: ${Thread.currentThread().getName}")
  unsafePerformIO(composition)
}

private def createIO(sentence:String):IO[Throwable,String] = {
  IO.point[Throwable, String](sentence)
    .map(sentence => {
      sentence.concat(s"$sentence ${Thread.currentThread().getName}").toUpperCase()
    }).delay(1 second)
}

Help me understand racing :)

OK, so here I thought race was straight-forward. Clearly I am doing something wrong...

import $ivy.`org.scalaz::scalaz-ioeffect:2.1.0`, scalaz._, ioeffect._, Scalaz._, scala.concurrent.duration._

object App extends SafeApp {
    type Error = Exception
  
    def run(args: List[String]): IO[Error, Unit] = {
      val io1 = IO.sleep[Error](10.seconds).fork[Error]
      val io2 = IO.point[Error, Unit]{ println("Hello"); Thread.sleep(500L) }.forever[Unit].fork[Error]
      io1.race(io2).toUnit
}

App.main(Array.empty)

I was under the impression the two IO would race each other and once the first one finishes (clearly the sleeper, since the other one is a forever guy), the slower one is interrupted and will never be heard of again.
In the above code io2 is completely unfazed by the race and will keep on running forever. Can an IO.forever not be interrupted?

Anyways, I changed things around a bit, thinking maybe one of the fibres is not allowed to be forked, and now I have this:

import $ivy.`org.scalaz::scalaz-ioeffect:2.1.0`, scalaz._, ioeffect._, Scalaz._, scala.concurrent.duration._

object App extends SafeApp {
  type Error = Exception

  def run(args: List[String]): IO[Error, Unit] = {
    val io1: IO[Error, Unit] = IO.sleep[Error](10.seconds).fork[Error].toUnit
    val io2: IO[Error, Unit] = IO.point(println("Hello")).forever[Unit]
    io1.race(io2)
  }
}

App.main(Array.empty)

a) The race lasts maybe 1 second, not 10, not forever
b) Sometimes I get a bunch of prints but usually only one


Here is essentially what I need (maybe there is a significantly better way to do this):

  • I have two IO[Error, Unit] (let's call them X and Y)
  • X runs forever (it's a streaming processor)
  • Y does a bunch of stuff, then completes
  • I need X to start, then Y to start. Once Y has completed, interrupt X, collect results, done

Request: Scala Native support

I’m building an app using Scala Native, and pure FP IO is something I’d like to use. It would be great for scalaz-ioeffect to support Scala Native 0.3 like scalaz-core, scalaz-effect, scalaz-iteratee, etc. How difficult is this from a technical perspective?

unwanted printlns in the default handler

I'm using IO.syncThrowable to invoke a legacy method that can throw an exception.

But even though that's supposed to capture the execption as a valid Task error, not an unexpected exception, I'm still getting the stacktrace dumped to the screen with

scalaz.ioeffect.Errors$UnhandledError: An error was not handled by a fiber: 

I can try to minimise it with an example if this is difficult to see by inspection.

Thread pool Shifting

@jdegoes I'm wondering is it possible or will be possible in future to shift thread pools? (one thread pool for CPU intense load, another one for blocking operations, etc).

IO.fromFuture

when integrating with existing code, having the ability to create a Task from some Future thing is essential.

But we don't seem to have anything like this... can we please add this?

I'm trying to migrate my work codebase to scalaz.ioeffect from cats-effect right now, so if there are any snippets that I can use as a workaround please do let me know.

note that cats has fromFuture[A](iofa: IO[Future[A]]): IO[A] = ...

which allows deciding if the future begins now or delayed.

IO requires Bimap

We currently do not have a bimap for IO. As a bifunctor this is necessary for calling it a bifunctor. If someone wants to implement the new tag and case of the IO runtime supporting it (for instance, as was done with the Map and FlatMap tags), that would be greatly appreciated.

Behave of catchAll

I´m learning the monad IO of scalaZ and I cannot understand how catchAll and catchSome operators works.
I was expecting so see a behave like the onError or onErrorrResumeNext of RxJava, but instead is not catching the throwable, and it´s just breaking the test and throwing the NullPointerException.

Here my two examples

  @Test
  def catchAllOperator(): Unit = {
    val errorSentence: IO[Throwable, String] =
      IO.point[Throwable, String](null)
        .map(value => value.toUpperCase())
        .catchAll(error => IO.fail(error))
    println(unsafePerformIO(errorSentence))

  }

And catchSome example

  @Test
  def catchSomeOperator(): Unit = {
    val errorFunction = new PartialFunction[Throwable /*Entry type*/ , IO[Throwable, String] /*Output type*/ ] {

      override def isDefinedAt(x: Throwable): Boolean = x.isInstanceOf[NullPointerException]

      override def apply(v1: Throwable): IO[Throwable, String] = IO.point("Default value")
    }

    val errorSentence = IO.point[Throwable, String](null)
      .map(value => value.toUpperCase())
      .catchSome(errorFunction)
    println(unsafePerformIO(errorSentence))

  }

Any idea what I´m doing wrong?.

Regards

MonadIO instances

I wonder if perhaps we should remove the extends Monad to be able to create instances for the scalaz mtl

`IO`s created with `par` fail with `ClassCastException` if performed within loop

So it seems something is going on wrong with par implementation, when performed in isolation it seems to work but it starts having unpredictable behavior when performed multiple consecutive times, I realized about this since I have some property-based test with default sampling of 100 performing some IO using par combinator.

You can find the test i'm talking about here: https://github.com/ktonga/scala-poc/blob/topic/parallel-io/src/test/scala/com/brickx/autoinvest/ProgramSpec.scala#L26

This tests used to run ok when IOs were combined using apply2 from default Applicative instance but started failing after I introduced the use of par in this WIP PR: ktonga/scala-poc#6

I'll try to add a minimal example that reproduces the bug to this project for easy debugging.

Cheers.

<url> Some(http://github.com/scalaz/effect) </url>

sbt makePom
cat target/scala-2.12/scalaz-ioeffect_2.12-0.0.1-SNAPSHOT.pom
<?xml version='1.0' encoding='UTF-8'?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.scalaz</groupId>
    <artifactId>scalaz-ioeffect_2.12</artifactId>
    <packaging>jar</packaging>
    <description>scalaz-ioeffect</description>
    <url>http://github.com/scalaz/effect</url>
    <version>0.0.1-SNAPSHOT</version>
    <licenses>
        <license>
            <name>BSD3</name>
            <url>https://opensource.org/licenses/BSD-3-Clause</url>
            <distribution>repo</distribution>
        </license>
    </licenses>
    <name>scalaz-ioeffect</name>
    <inceptionYear>2017</inceptionYear>
    <organization>
        <name>org.scalaz</name>
        <url>http://github.com/scalaz/effect</url>
    </organization>
    <scm>
        <url> Some(http://github.com/scalaz/effect) </url>

addSbtPlugin("com.fommil" % "sbt-sensible" % "2.4.1") bug ? 🤔
https://gitlab.com/fommil/sbt-sensible/blob/36ed88c76e7b249571b951c8ac653ba66b5b00e7/src/main/scala/SonatypePlugin.scala#L131
/cc @fommil

Minor typo in readme

Readme currently reads:

  def run(args: List[String]): IO[Void, ExitStatus] =
    myAppLogic.attempt.map(_.fold(_ => 1)(_ => 0)).map(ExitStatus.ExitNow(_))

It should read:

  def run(args: List[String]): IO[Void, ExitStatus] =
    myAppLogic.attempt.map(_.fold(_ => 1, _ => 0)).map(ExitStatus.ExitNow(_))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.