项目作者: aedans

项目描述 :
Kotlin recursion schemes with Arrow
高级语言: Kotlin
项目地址: git://github.com/aedans/Katalyst.git
创建时间: 2017-11-23T22:45:46Z
项目社区:https://github.com/aedans/Katalyst

开源协议:MIT License

下载


Katalyst

Notice: Katalyst has been merged with Arrow to create arrow-recursion and is no longer being maintained. See The Arrow Website and The Arrow Recursion Docs instead.

Download

Kotlin recursion schemes with Arrow.

Gradle

  1. repositories {
  2. maven { url 'https://dl.bintray.com/aedans/maven/' }
  3. }
  4. dependencies {
  5. compile 'io.github.aedans:katalyst:$katalyst_version'
  6. }

Features

  • Mu, Nu, and Fix data types
  • Recursive, Corecursive, and Birecursive typeclasses
  • Cata, ana, and hylo recursion schemes
  • EnvT and CoEnv data types
  • List and Nat defined using recursion schemes
  • Kleisli recursion schemes
  • Generalized recursion schemes
  • Advanced recursion schemes (para, apo, histo, futu, etc.)
  • Free and Cofree defined using recursion schemes
  • Recursive and Corecursive instances for Free and Cofree
  • Elgot recursion schemes

Code sample

  1. // Define an expression pattern type
  2. @higherkind
  3. sealed class ExprPattern<out A> : ExprPatternOf<A> {
  4. class Int(val value: kotlin.Int) : ExprPattern<Nothing>()
  5. class Neg<out A>(val expr: A) : ExprPattern<A>()
  6. class Plus<out A>(val expr1: A, val expr2: A) : ExprPattern<A>()
  7. companion object
  8. }
  9. // Create a Functor instance for the expression pattern
  10. @instance(ExprPattern::class)
  11. interface ExprPatternFunctorInstance : Functor<ForExprPattern> {
  12. override fun <A, B> ExprPatternOf<A>.map(f: (A) -> B) = run {
  13. val fix = fix()
  14. when (fix) {
  15. is ExprPattern.Int -> fix
  16. is ExprPattern.Neg -> ExprPattern.Neg(f(fix.expr))
  17. is ExprPattern.Plus -> ExprPattern.Plus(f(fix.expr1), f(fix.expr2))
  18. }
  19. }
  20. }
  21. // Expand the expression pattern with a recursive type
  22. typealias Expr = FixOf<ForExprPattern>
  23. // Define convenience functions for constructing expressions
  24. fun int(i: Int) = Fix(ExprPattern.Int(i))
  25. fun neg(e: Expr) = Fix(ExprPattern.Neg(Eval.now(e)))
  26. fun plus(a: Expr, b: Expr) = Fix(ExprPattern.Plus(Eval.now(a), Eval.now(b)))
  27. // Define an algebra to evaluate an expression
  28. fun evalExprAlgebra() = Algebra<ForExprPattern, Eval<Int>> {
  29. val fix = it.fix()
  30. when (fix) {
  31. is ExprPattern.Int -> Eval.now(fix.value)
  32. is ExprPattern.Neg -> fix.expr.map { -it }
  33. is ExprPattern.Plus -> Eval.monad().binding { fix.expr1.bind() + fix.expr2.bind() }.ev()
  34. }
  35. }
  36. // Use recursion schemes to generically apply algebras
  37. fun main(args: Array<String>) {
  38. val expr = plus(plus(int(1), int(2)), neg(plus(int(3), int(4))))
  39. Fix.recursive().run {
  40. expr.cata(evalExprAlgebra(), ExprPattern.functor()) // -4
  41. }
  42. }

Resources

Recursion Schemes, the
original Haskell implementation.

Matryoshka, which
much of Katalyst’s code is based off of.