All Projects → typelevel → Cats Tagless

typelevel / Cats Tagless

Licence: apache-2.0
Library of utilities for tagless final encoded algebras

Programming Languages

scala
5932 projects

Projects that are alternatives of or similar to Cats Tagless

Bitcoin Chart Cli
Bitcoin chart for the terminal as command line util
Stars: ✭ 221 (-7.14%)
Mutual labels:  functional-programming
Functional Programming Jargon
Jargon from the functional programming world in simple terms!
Stars: ✭ 14,351 (+5929.83%)
Mutual labels:  functional-programming
Poica
🧮 A research programming language on top of C macros
Stars: ✭ 231 (-2.94%)
Mutual labels:  functional-programming
Domainmodelingmadefunctional
Extended code samples related to the book "Domain Modeling Made Functional". Buy the book here: https://pragprog.com/book/swdddf/domain-modeling-made-functional or here https://fsharpforfunandprofit.com/books/
Stars: ✭ 223 (-6.3%)
Mutual labels:  functional-programming
Funcy
A fancy and practical functional tools
Stars: ✭ 2,690 (+1030.25%)
Mutual labels:  functional-programming
Program Blog
Practice, thinking and reading
Stars: ✭ 228 (-4.2%)
Mutual labels:  functional-programming
Nix 1p
A (more or less) one page introduction to Nix, the language.
Stars: ✭ 219 (-7.98%)
Mutual labels:  functional-programming
Unchanged
A tiny, fast, unopinionated handler for updating JS objects and arrays immutably
Stars: ✭ 237 (-0.42%)
Mutual labels:  functional-programming
Functional Light Js
Pragmatic, balanced FP in JavaScript. @FLJSBook on twitter.
Stars: ✭ 14,764 (+6103.36%)
Mutual labels:  functional-programming
Elm Ts
A porting to TypeScript featuring fp-ts, rxjs6 and React
Stars: ✭ 230 (-3.36%)
Mutual labels:  functional-programming
Odin
Fast & Functional logger in Scala
Stars: ✭ 225 (-5.46%)
Mutual labels:  functional-programming
Wonder.js
🚀Functional, High performance 3D Webgl Engine
Stars: ✭ 225 (-5.46%)
Mutual labels:  functional-programming
Arturo
Simple, expressive & portable programming language for efficient scripting
Stars: ✭ 225 (-5.46%)
Mutual labels:  functional-programming
Eta
The Eta Programming Language, a dialect of Haskell on the JVM
Stars: ✭ 2,507 (+953.36%)
Mutual labels:  functional-programming
Bash Fun
Functional programming in bash
Stars: ✭ 232 (-2.52%)
Mutual labels:  functional-programming
React Organism
Dead simple React state management to bring pure components alive
Stars: ✭ 219 (-7.98%)
Mutual labels:  functional-programming
Functional intro to python
[tutorial]A functional, Data Science focused introduction to Python
Stars: ✭ 228 (-4.2%)
Mutual labels:  functional-programming
Cats Mtl
cats transformer type classes.
Stars: ✭ 238 (+0%)
Mutual labels:  functional-programming
Neither
Either and Maybe monads for better error-handling in C++ ↔️
Stars: ✭ 236 (-0.84%)
Mutual labels:  functional-programming
Curryhoward
Automatic code generation for Scala functions and expressions via the Curry-Howard isomorphism
Stars: ✭ 229 (-3.78%)
Mutual labels:  functional-programming

Typelevel incubator Build Status codecov Join the chat at https://gitter.im/typelevel/cats-tagless Scala.js Latest version

Cats-tagless is a small library built to facilitate transforming and composing tagless final encoded algebras.

Installation

Cats-tagless is currently available for Scala 2.12 and 2.13 and Scala.js.

Add the following settings in build.sbt

libraryDependencies += 
  "org.typelevel" %% "cats-tagless-macros" % latestVersion  //latest version indicated in the badge above

Compile / scalacOptions ++= {
  CrossVersion.partialVersion(scalaVersion.value) match {
    case Some((2, n)) if n >= 13 => "-Ymacro-annotations" :: Nil
    case _ => Nil
  }
}

libraryDependencies ++= {
  CrossVersion.partialVersion(scalaVersion.value) match {
    case Some((2, n)) if n >= 13 => Nil
    case _ => compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) :: Nil
  }
}

Auto-transforming tagless final interpreters

Say we have a typical tagless encoded algebra ExpressionAlg[F[_]]

import cats.tagless._

@autoFunctorK
trait ExpressionAlg[F[_]] {
  def num(i: String): F[Float]
  def divide(dividend: Float, divisor: Float): F[Float]
}

With Cats-tagless you can transform this interpreter using Cats' FunctionK, i.e, you can transform an ExpressionAlg[F] to an ExpressionAlg[G] using a FunctionK[F, G], a.k.a. F ~> G. Cats-tagless generates a FunctorK instance for your algebra.

The @autoFunctorK annotation adds the following line (among some other code) in the companion object.

object ExpressionAlg {
  implicit def functorKForExpressionAlg: FunctorK[ExpressionAlg] =
      Derive.functorK[ExpressionAlg]
}

This functorKForExpressionAlg is a FunctorK instance for ExpressionAlg which can map a ExpressionAlg[F] to a ExpressionAlg[G] using a FunctionK[F, G].

Note that the usage of @autoFunctorK, like all other @autoXXXX annotations provided by cats-tagless, is optional, you can manually add this instance yourself.

For example, if you have an interpreter of ExpressionAlg[Try]

import util.Try

object tryExpression extends ExpressionAlg[Try] {
  def num(i: String) = Try(i.toFloat)
  def divide(dividend: Float, divisor: Float) = Try(dividend / divisor)
}

You can transform it to an interpreter of ExpressionAlg[Option]

import cats.tagless.implicits._
import cats.implicits._
import cats._

val fk : Try ~> Option = λ[Try ~> Option](_.toOption)

tryExpression.mapK(fk)
// res0: ExpressionAlg[Option]

Note that the Try ~> Option is implemented using kind projector's polymorphic lambda syntax.

Obviously, FunctorK instance is only possible when the effect type F[_] appears only in the covariant position (i.e. the return types). For algebras with effect type also appearing in the contravariant position (i.e. argument types), Cats-tagless provides a InvariantK type class and an autoInvariantK annotation to automatically generate instances.

@autoFunctorK also add an auto implicit derivation, so that if you have an implicit ExpressionAlg[F] and an implicit F ~> G, you can automatically have a ExpressionAlg[G]. It works like this

import ExpressionAlg.autoDerive._

implicitly[ExpressionAlg[Option]]  //implicitly derived from a `ExpressionAlg[Try]` and a `Try ~> Option`

This auto derivation can be turned off using an annotation argument: @autoFunctorK(autoDerivation = false).

Quick example: make stack safe with Free

With Cats-tagless, you can lift your algebra interpreters to use Free to achieve stack safety.

For example, say you have an interpreter using Try

@finalAlg @autoFunctorK
trait Increment[F[_]] {
  def plusOne(i: Int): F[Int]
}

implicit object incTry extends Increment[Try] {
  def plusOne(i: Int) = Try(i + 1)
}

def program[F[_]: Monad: Increment](i: Int): F[Int] = for {
  j <- Increment[F].plusOne(i)
  z <- if (j < 10000) program[F](j) else Monad[F].pure(j)
} yield z

Obviously, this program is not stack safe.

program[Try](0)
//throws java.lang.StackOverflowError

Now, let's use auto derivation to lift the interpreter with Try into an interpreter with Free

import cats.free.Free
import cats.arrow.FunctionK
import Increment.autoDerive._

implicit def toFree[F[_]]: F ~> Free[F, *] = λ[F ~> Free[F, *]](t => Free.liftF(t))

program[Free[Try, *]](0).foldMap(FunctionK.id)
// res9: scala.util.Try[Int] = Success(10000)

Again, the magic here is that Cats-tagless auto derive an Increment[Free[Try, *]] when there is an implicit Try ~> Free[Try, *] and a Increment[Try] in scope. This auto derivation can be turned off using an annotation argument: @autoFunctorK(autoDerivation = false).

Horizontal composition with @autoSemigroupalK

You can use the SemigroupalK type class to create a new interpreter that runs both interpreters and return the result as a cats.Tuple2K. The @autoSemigroupalK attribute adds an instance of SemigroupalK to the companion object. Example:

@autoSemigroupalK
trait ExpressionAlg[F[_]] {
  def num(i: String): F[Float]
  def divide(dividend: Float, divisor: Float): F[Float]
}


val prod = tryExpression.productK(optionExpression)
prod.num("2")
// res11: cats.data.Tuple2K[Option,scala.util.Try,Float] = Tuple2K(Some(2.0),Success(2.0))

If you want to combine more than 2 interpreters, the @autoProductNK attribute adds a series of product{n}K (n = 3..9) methods to the companion object. Unlike productK living in the SemigroupalK type class, currently we don't have a type class for these product{n}K operations yet.

@autoFunctor, @autoInvariant and @autoContravariant

Cats-tagless also provides three annotations that can generate cats.Functor, cats.Invariant cats.Contravariant instance for traits.

For documentation/FAQ/guides, go to typelevel.github.io/cats-tagless.

Community

Any contribution is more than welcome. Also feel free to report bugs, request features using github issues or gitter.

Discussion around Cats-tagless is encouraged in the Gitter channel as well as on Github issue and PR pages.

We adopted the Scala Code of Conduct. People are expected to follow it when discussing Cats-tagless on the Github page, Gitter channel, or other venues.

Maintainers

Copyright

Copyright (C) 2019 Maintainers of Cats-tagless

License

Cats-tagless is licensed under the Apache License 2.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].