Code Monkey home page Code Monkey logo

cats's Introduction

Cats

Cats graphic

cats-core Scala version support Continuous Integration Financial Contributors on Open Collective Discord

Overview

Cats is a library which provides abstractions for functional programming in the Scala programming language.

Scala supports both object-oriented and functional programming, and this is reflected in the hybrid approach of the standard library. Cats strives to provide functional programming abstractions that are core, binary compatible, modular, approachable and efficient. A broader goal of Cats is to provide a foundation for an ecosystem of pure, typeful libraries to support functional programming in Scala applications.

For more detail about Cats' motivations, go here.

Why "cats"?

The name is a playful shortening of the word category, from "category theory".

Regardless, you do not need to know anything about category theory to use Cats.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. We welcome contributions to Cats and would love for you to help build Cats. See our contributor guide for more information about how you can get involved as a developer. If you are looking for something to start with, here is a beginner friendly list.

Financial Contributors

Become a financial contributor and help us sustain our community. Donations directly support office hours for maintainers, better documentation and strategic initiatives.

Platinum Sponsors

Platinum sponsorship starts at $950 USD/month.
Platinum Sponsors appear here at https://typelevel.org/cats

Gold Sponsors

Gold Sponsorship starts at $420 USD/month.
Gold Sponsors appear here at https://typelevel.org/cats

Silver Sponsors

Silver Sponsorship starts at $180 USD/month.
Silver Sponsors appear here at https://typelevel.org/cats

Backers

Become a Backer with a recurring donation of just $5 USD/month.
Backers appear here at https://typelevel.org/cats

Other contributors

We thankfully accept one-time and recurring contributions as well.
Other contributors appear here at https://typelevel.org/cats
<script src="/cats/js/sponsors.js"></script>

Getting Started

Cats is available for Scala.js and Scala Native, as well as the standard JVM runtime.

Cats relies on improved type inference via the fix for SI-2712, which is not enabled by default. For Scala 2.12 you should add the following to your build.sbt:

scalacOptions += "-Ypartial-unification"

(Partial unification is on by default since Scala 2.13, the compiler no longer accepts -Ypartial-unification)

And then create the Cats dependency, by adding the following to your build.sbt:

libraryDependencies += "org.typelevel" %% "cats-core" % "2.9.0"

This will pull in the cats-core module. If you require some other functionality, you can pick-and-choose from amongst these modules (used in place of "cats-core"):

  • cats-kernel: Small set of basic type classes (required).
  • cats-core: Most core type classes and functionality (required).
  • cats-laws: Laws for testing type class instances.
  • cats-free: Free structures such as the free monad, and supporting type classes.
  • cats-testkit: lib for writing tests for type class instances using laws.
  • algebra: Type classes to represent algebraic structures.
  • alleycats-core: Cats instances and classes which are not lawful.

There are several other Cats modules that are in separate repos so that they can maintain independent release cycles.

  • cats-effect: standard IO type together with Sync, Async and Effect type classes
  • cats-mtl: transformer typeclasses for Cats' Monads, Applicatives and Functors.
  • mouse: a small companion to Cats that provides convenient syntax (aka extension methods)
  • kittens: automatic type class instance derivation for Cats and generic utility functions
  • cats-tagless: Utilities for tagless final encoded algebras
  • cats-collections: Data structures which facilitate pure functional programming
  • cats-testkit-scalatest: Cats testkit integration with Scalatest

Past release notes for Cats are available in CHANGES.md.

Documentation

Links:

  1. Website: typelevel.org/cats/
  2. ScalaDoc: typelevel.org/cats/api/
  3. Type classes: typelevel.org/cats/typeclasses.html
  4. Data types: typelevel.org/cats/datatypes.html
  5. Algebra overview: typelevel.org/cats/algebra.html
  6. Glossary: typelevel.org/cats/nomenclature.html
  7. Resources for Learners: typelevel.org/cats/resources_for_learners.html
  8. FAQ: typelevel.org/cats/faq.html
  9. The Typelevel Ecosystem: typelevel.org/cats/typelevelEcosystem.html

Community

Discussion around Cats is currently happening on GitHub issues, PR pages, and Discord:

The Typelevel Discord has #cats and #cats-dev channels, as well as community channels such as #beginners. Please join us!

People are expected to follow the Scala Code of Conduct when discussing Cats on GitHub, Discord, or other venues.

We hope that our community will be respectful, helpful, and kind. If you find yourself embroiled in a situation that becomes heated, or that fails to live up to our expectations, you should disengage and contact one of the project maintainers in private. We hope to avoid letting minor aggressions and misunderstandings escalate into larger problems.

If you are being harassed, please contact one of us immediately so that we can support you.

Binary compatibility and versioning

After 1.0.0 release, we decided to use MAJOR.MINOR.PATCH Semantic Versioning 2.0.0 going forward, which is different from the EPOCH.MAJOR.MINOR scheme common among Java and Scala libraries (including the Scala lang).

Cats strives to provide a solid and stable foundation for an ecosystem of FP libraries. Thus, we treat backward binary compatibility maintenance with a high priority. In semantic versioning, backward breaking change is ONLY allowed between MAJOR versions. We will maintain backward binary compatibility between PATCH AND MINOR versions. For example, when we release Cats 1.1.0, it will be backward binary compatible with the previous 1.0.x versions. I.E. the new JAR will be a drop-in replacement for the old one. This is critical when your application has a diamond dependency on Cats - depending on two or more libraries that all depend on Cats. If one library upgrades to the new 1.1.0 Cats before the other one does, your application still runs thanks to this backward binary compatibility.

Also worth noting is that according to semantic versioning, MINOR version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API. It MUST be incremented if any public API functionality is marked as deprecated.

Any binary breaking changes will require a MAJOR version bump, which we will be very cautious about. We will also consider using organization and package name for major versioning in the future. But that decision is yet to be made.

Adopters

A (non-exhaustive) list of companies that use Cats in production is featured in ADOPTERS.md. Don't see yours? You can add it in a PR! And if you can, consider supporting us.

Maintainers

The current maintainers (people who can merge pull requests) are:

Retired committers include:

We are currently following a practice of requiring at least two sign-offs to merge code PRs (and for large or contentious issues we may wait for more). For typos, documentation improvements or minor build fix we relax this to a single sign-off. More detail in the process document.

Copyright and License

All code is available to you under the MIT license, available at http://opensource.org/licenses/mit-license.php and also in the COPYING file. The design is informed by many other projects, in particular Scalaz.

Copyright the maintainers, 2015-2023.

cats's People

Contributors

adelbertc avatar alistair-johnson avatar armanbilge avatar barambani avatar benkio avatar bplommer avatar ceedubs avatar danicheg avatar djspiewak avatar erik-stripe avatar fthomas avatar johnynek avatar jorokr21 avatar julien-truffaut avatar kailuowang avatar larsrh avatar lukajcb avatar mikejcurry avatar mpilquist avatar non avatar oscar-stripe avatar peterneyens avatar raulraja avatar rossabaker avatar satorg avatar scala-steward avatar stew avatar timwspence avatar travisbrown avatar typelevel-steward[bot] 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  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  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  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

cats's Issues

remove bijection

or really any typeclass. We got burned with an early version of twitter/bijection that did this. It meant having an implicit bijection in scope gave you an implicit conversion.

Justify Bimonad

Per a conversation with Kmett that I only understood about 10% of (i.e., better than usual) the notion of Bimonad is interesting only if the Monad and Comonad instances are each others' co-algebras, otherwise we can't say anything interesting. It's also not clear whether these things we can say lead to useful derived operations. So I suggest removing Bimonad unless we can state its law and identify operations that it provides; closing the diamond is fun but not reason enough.

Stack safety of lazy version of `foldRight` for `List`

Cats defines a lazy version of foldRight on Foldable:

def foldRight[A, B](fa: List[A], b: Lazy[B])(f: (A, Lazy[B]) => B): Lazy[B] = {

Currently the List implementation is properly lazy, but it is not stack safe.

For example, consider the following derived Foldable method:

def exists[A](fa: F[A])(f: A => Boolean): Boolean =
  foldRight(fa, Lazy.eager(false))((a, b) => f(a) || b.force).force

This implementation will properly short-circuit for a small list:

scala> Foldable[List].exists(List(1, 2, 3)){x => println(x); x > 1}
1
2
res0: Boolean = true

However, for a large list it will throw a StackOverflowError. If a List is long enough that evaluating the predicate for each element is bad (and thus the Lazy variant is preferred), then it is likely large enough to throw this error. Therefore something needs to give.

Solutions that come to mind:

  1. Use a version of foldRight for List that uses a combination of reverse and foldLeft. This would sacrifice laziness.
  2. Use trampolining in the List implementation of the Lazy variant of foldRight. The trampolining would add significant overhead, but laziness would be preserved.

The second version seems preferable to me. If somebody is choosing to explicitly call the lazy (as opposed to strict) version, then they should get laziness.

However, I can also see the possibility of the abstraction becoming somewhat leaky. That is, someone defining def foo[F[_]: Foldable]... may start to think about which kinds of F people are going to be passing into this method so they can decide whether they want potential overhead of laziness or not. Having said that, it seems to me that the abstraction is still pretty leaky (or flat out wrong) if the types are suggesting they will get lazy evaluation but they don't.

What do people think? Beyond just choosing option 1 or option 2, are there other possibilities that come to mind?

Bifoldable

Bifoldable is a type class (currently not in cats) for a type that has two separate Foldables. For example, Or has a Foldable instance (via its Traverse instance) that folds over the RightOr case, but Or could equally fold over the LeftOr case.

One of my favorite methods from scalaz is MonadPlus.separate. This can do things like take a List[A Or B] and turn it into a (List[A], List[B]). Or similarly, take a List[(A, B)] and turn it into a (List[A], List[B]). In Cats, I believe we could implement the same sort of method on MonadFilter if we were to bring in a Bifoldable type class.

What do people think? Is this something that would belong in core?

Organization of AnyRef instances

Currently the BigInt and BigDecimal instances reside in anyref.scala and are mixed into AnyRefInstances. Since we have other AnyRef instances (String, Option, etc), this seems kind of odd to me. Should they just get their own files and instance traits like other std lib types?

Where do arbitrary data instances go?

We need to decide on a home for arbitrary instances of cats.data types.

  1. cats-laws could depend on cats-data. This is simplest.
  2. We could establish a new module, cats-data-laws, which pulls in both cats-laws and cats-data. This is better for future projects that build on cats-core without cats-data.

Add instances for std Either

Either from the standard library is isomorphic to Or and should have instances for all of the same type classes that Or does.

add typeclass instances for scala std Future

I still have to use scala std Future a lot so... this would be quite useful. I think at least Monad, Comonad and Monoid should be implemented. I volunteer to implement them over the weekend.

Annotate the types of implicit instances

As @retronym says:

I'd suggest to annotate the types of implicits as a rule around the code base.
It is too easy to have overly-specific structural types inferred for
implicit val fooInstance = new A with B { .... }

Revisit the Or datatype

We now have a Or datatype in -data which is mostly lifted straight out of scalaz.

Right now it is

data Or a = LOr a | Ror a

We thought about -Or and Or- for constructors but the compiler seemed unhappy about. I don't think anyone loves the name LOr or ROr, but nobody seems to have a slam-dunk replacement. We're going to move on for now, but the discussion around this raised several questions we should revisit:

  1. What are good names for these constructors, some suggestions i've heard:
    Bad | Good
    \Or | Or/
    Dead | Alive
  2. do we want public constructors at all on these? Can we have just a catamorphism? Can we have smart constructors and extractors so that we can still pattern match?
  3. Do we want to tend not to just lift code out of scalaz, perhaps we would re-think some of the decisions made in scalaz and tend to have a better chance of improving things if we are writing everything new

document methods in Foldable.scala

see #62 as a separate issue for the lazy foldRight, which I thought deserved special attention, but the rest of the methods in Foldable also deserve documentation.

My tendency would be to also give special attention to sequence_ and traverse_ as they are side-effecty and side-effecty demands more documentaiton

Create Contributor's Guide

I've mentioned this while talking to many people, so I think it's something that we should get started on sooner rather than later.

Here are some things I imagine it doing:

  1. Set expectations for contributors
  2. Explain basic workflow, discussions, PR process, etc.
  3. Talk about project structure, modules, etc.
  4. Explain fundamental guiding principles
  5. Lay out best practices and encourage consistency
  6. Clearly document any exceptions or gotchas

We could use a wiki but I think I'd prefer a single Markdown document. I will try to start on this ASAP.

Attempt to implement type classes without inheritance

in scalaz and cats, type classes are defined as trait with inheritance to express facts like all Monad are an Applicative. This leads to some ambiguous implicit resolutions and as far as I know, the solution is to create a hierarchy of traits to guide implicit search. It also creates ambiguous implicit when you have two imports that brings the same implicit in scope e.g.

import scalaz.syntax.traverse._ 
import scalaz.syntax.foldable._

I wonder if it would be possible and desirable to implement type classes using abstract class and implicit evidence to express the hierarchy between two type classes:

abstract class Equal[T]{
  def eq(v1: T, v2: T): Boolean
}

object Equal{
  def apply[T](implicit ev: Equal[T]): Equal[T] = ev
  def equalA[T]: Equal[T] = new Equal[T] {
    def eq(v1: T, v2: T): Boolean = v1 == v2
  }

  implicit val intEqual = equalA[Int]
}

abstract class Ord[T: Equal]{
  def lowerThan(v1: T, v2: T): Boolean
  def lowerThanOEqual(v1: T, v2: T): Boolean = lowerThan(v1, v2) || Equal[T].eq(v1, v2)
  def greaterThan(v1: T, v2: T): Boolean = !lowerThan(v1, v2)
  def greaterThanOEqual(v1: T, v2: T): Boolean = greaterThan(v1, v2) || Equal[T].eq(v1, v2)
}

object Ord{
  def apply[T](implicit ev: Ord[T]): Ord[T] = ev
  def fromLowerThan[T: Equal](lth: (T, T) => Boolean): Ord[T] = new Ord[T] {
    def lowerThan(v1: T, v2: T) = lth(v1, v2)
  }

  implicit val intOrd = fromLowerThan[Int](_ < _)
}

I haven't tried this technique extensively, so it might in fact causes more issues that inheritance. However, I thought it make sense to discuss this option since you are just starting cats.

Add linter for conventions and style

This may need to be a longer-term goal, but in my view providing a linter is one of the single most important things a project can do to promote contribution.

I definitely agree that we should be documenting conventions like #27, but having to parse a bunch of guidelines in prose (and then extrapolate from the current source when the guidelines aren't 100% unambiguous, which is always) can be stressful—I know that I'm personally a lot less likely to click the submit button on local work if I'm worried that it's going to be picked apart because I didn't understand all the details of the project's contributor guidelines (and that's even if I don't think the maintainers are going to be dismissive or condescending). Being able to go through a few rounds of local correction for formatting and convention before I put something in public is hugely confidence-building.

I like both WartRemover and Scalastyle, but I'm not sure either is a perfect solution to this problem.

Fix Gitter intergration

I've done the manual set up a few times with no luck.

This issue exists solely so I can comment on it, change it, etc. to test Gitter integration.

Set precedent for tests

Currently we really don't have any tests other than some law-checking. We should set a precedent for tests that will be easy for others to follow as the contribute.

Typeclass instance usage convention

The two implementations are effectively identical:

implicit def OrShow1[A: Show, B: Show]: Show[A Or B] =
  Show.show[A Or B](_.fold(a => s"LOr(${Show[A].show(a)})", b => s"ROr(${Show[B].show(b)})"))

implicit def OrShow2[A, B](implicit showA: Show[A], showB: Show[B]): Show[A Or B] =
  Show.show[A Or B](_.fold(a => s"LOr(${showA.show(a)})", b => s"ROr(${showB.show(b)})"))

In order to make it easier for newcomers to contribute, I think cats should establish and document a convention for which of the two approaches to use.

Here is a proposed convention:
If your function needs to call a method on the type class instance, it should use the latter approach. This prevents the unnecessary calls to Show.apply.
If your function just needs the evidence of the type class instances so it can call through to another function that requires them, it should use the former aproach, as it is a bit cleaner.

There are also questions about whether you should use names like showA: Show[A] or ShowA: Show[A] or A: Show[A], etc. I don't really have a preference on convention here, but I think the more of this we can put into a contributor guide the less people have to worry about not knowing the right way to do it or submitting a pull request that gets nitpicked.

Thoughts?

Try[A] => Throwable Or A

We should provide a helper method to convert Try[A] into Throwable Or A.

It probably makes sense to put this on the Or companion object, because the std module does not depend on the data module. However, this does raise the question of whether we are going to have syntax for things like Try.toOr, Either.toOr. List.toNonEmptyList, etc. If so, where would it go?

Also this could be implemented as an isomophism with something like Try <~> Or[Throwable, ?], but as far as I know we don't have this sort of isomorphism defined in Cats. Do we want it?

Data structure methods

shall we implement type class methods (e.g. map, show) on data structures in cats.data or shall we get them via ops implicit classes?

cats.concurrent and cats.stream

A goal of some contributors is to build an alternative to scalaz-stream.

There are a some cases (like https://github.com/tpolecat/doobie) where scalaz-stream is used with a different monad but most applications use scalaz.concurrent.Task which in turn wraps scalaz.concurrent.Future.

Are people generally satisfied with the design of scalaz's Task and Future? Should cats seek to follow a generally similar design or do something different? Does the scope of cats include these tools or would another project be appropriate?

How to encode typeclasses that require Either

Choice, ProChoice and probably other typeclasses have methods that take or produce Either. Ideally, we would use cats.data.Or instead of scala.Either but it means that Or need to be defined in core.

What is your thought?

re-export typeclass instances from algebra

non says, "it would be nice if cats.std.string._ gave you Show[String] but also Monoid[String]. which would just mean having an object that repackages the string implicits from algebra
so the user doesn't have to care where things live."

add typeclass instances for Map

std should have typeclass instances for Map,

Map[K,?] should have instances for FlatMap, Traverse

Map[?,?] should have instances for Show

Project for instances and classes that aren't lawful

Instances in cats are checked against the type class laws. People may find certain things useful that either don't have governing laws or don't always obey them. For example, consider the following type class:

trait Foreach[F[_]]  { 
  def foreach[A](fa: F[A])(f: A => Unit): Unit
}

This type class has no meaningful laws. However, it could potentially be useful as an alternative to something like traversing a list into IO. The latter can lead to either stack overflows or excessive overhead for trampolining.

There should be a separate project to provide these sorts of things. @non has cleverly suggested the name alley-cats for such a project.

Set up gh-pages

Will be helpful after #17 is done, so we have a way for people to view the fantastic typechecked doc.

README updates

  • better placement for the waffle.io badge
  • "How can I contribute"
  • "what to do in the case of mis-communication, I've been harmed, I think ____ is a bad actor"
  • mention the "meta" label for issues

Scala.JS support

I would like to check how much interest there is in taking Scala.JS seriously in cats.

That might not be an easy decision to make but it could actually be :-)

A cats asynchronous monad (eg Task)

As discussed in #21, an asynchronous monad like the scalaz Task would be highly desirable for a variety of reasons including any possible streaming solution. The scalaz Task is very nice in many ways, but @tpolecat and I think it could possibly be improved. This would seem to not be a high priority at the moment, but would be nice to get on the radar.

One such issue with scalaz Task is stack overflows using Task.async.

add higher arity methods to apply

apply3, map3, apply4, map4... don't know if we should have some uniform arity where these things stop, in scalaz it is all over the place, some of these stop at 5 some at 8 some at 12, etc...

Add sbt task to validate a pull request?

The contributor guide mentions that one should run the compile, unidoc, and scalastyle tasks before submitting a PR. It would be nice if those could be subsumed under a new validateMyPR task so that you have to remeber only one task to run before submitting a PR.

Put laws next to type class definitions?

I'd like to discuss if the laws that govern the functions of type classes should be put next to their definitions. Here is an example of what I have in mind:

// this is Functor.scala

trait Functor[F[_]]  {
  def map = ...
}

trait FunctorLaws[F[_]: Functor] {
  def identity(...): Boolean = ...
  def associative(...): Boolean = ...
}

I see the following advantages:

  • it emphasizes the importance of laws
  • the type checked laws are in the vicinity of the type class definitions and not "hidden" between test code in the laws subproject
  • the laws can be used in the laws subproject
  • the laws are decoupled from test code

What do you think?

List-like structure with efficient appends

I think it would be handy to have a list-like structure that supports efficient appends. This is handy for many use-cases, such as using a writer monad for logging.

The most obvious candidate is a difference list.

Do others agree that something like this should be in the data module? Are there any alternatives to difference lists that should be considered?

Travis CI integration

I would imagine that we all want this to verify pull requests before they are merged (though please speak up if you have a reason not to go with Travis).

Anyone should be able to submit a PR with a .travis.yml. I think @non will probably have to be the one to enable it as described here.

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.