question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add ChainRec type class

See original GitHub issue

TailRec - A type class which captures stack-safe monadic tail recursion.

It would be nice to have a common specification for Tail Recursive Monads in JS community, so that libraries like Free could use the interface to be stack safe.

in PS MonadRectype class looks like this:

class Monad m <= MonadRec m where
  tailRecM :: forall a b. (a -> m (Either a b)) -> a -> m b

So we could have something like this without stack overflow:

Identity.tailRecM((n) => {
  if (n == 0) {
    return Identity(Either.Right("DONE"))
  }
  return Identity(Either.Left(n - 1))
})(20000)

one thing is that there are multiple Either implementations in js and this spec should depend on bare minimum from any Either type. from what I have found the minimum api from Either type is to have a cata method. but before that let’s see an implementation of tailRecM of Identity:

const tailRec = (f) => (a) => {
  let v = f(a)
  while (!isDone(v)) {
    v = f(getValue(v))
  }
  return getValue(v)
}

const runIdentity = (i) => i.x

Identity.tailRecM = (f) => (a) => Identity(tailRec((v) => runIdentity(f(v)))(a))

So we have seen usage of it and part of it’s implementation. now what we have left is implement isDone and getValue so that they are as generic as possible.

const isDone = (e) => e.cata({
  Right: () => true,
  Left: () => false,
})

const getValue = (e) => e.cata({
  Right: (v) => v,
  Left: (v) => v,
})

so as it looks any Either with cata would work so users shouldn’t be tied to some particular Either implementation (as long as it has cata). To note this Either implementation would work with tailRecM.

const Either = {
  Right: (v) => ({ cata: (c) => c.Right(v) }),
  Left: (v) => ({ cata: (c) => c.Left(v) }),
}

The hardest was to implement tailRecM for Task/Future but i have made it and after we agree on some interface I would create PRs for some popular Task/Future implementations

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:65 (63 by maintainers)

github_iconTop GitHub Comments

3reactions
SimonRichardsoncommented, Sep 1, 2016

I like how we’ve managed to rope @garyb into this. Welcome to the darkside! 👋

3reactions
scott-christophercommented, Aug 31, 2016

In the sense of accessibility, using done/next is better for newcomers, and even ones who understand Either, might get confused which one to use for looping/returning.

Another option would be to provide the Left & Right constructors as arguments to the function given to tailRecM.

tailRecM :: MonadRec m => (a -> (b -> Either b c) -> (c -> Either b c) -> m (Either a a)) -> a -> m a

Which would look like the following to a user:

Identity.tailRecM((n, next, done) => n == 0 ? done("DONE") : next(n - 1))(20000)

This has the advantage of avoiding naming things all together, though at the expense of being a little more difficult to describe in the spec.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Add support for chainRec · Issue #35 · gcanti/flow-static-land · GitHub
Add support for chainRec #35 ... I think initially the idea of fantasy-land was to provide specification for type classes and not for...
Read more >
ChainRec.ts - fp-ts
ChainRec (interface) · ChainRec1 (interface) · ChainRec2 (interface) · ChainRec2C (interface) · ChainRec3 (interface) · ChainRec3C (interface) · ChainRec4 (interface).
Read more >
What is the underlying idea of chainRec? - Stack Overflow
This is a follow-up question of How to implement a stack-safe chainRec operator for the continuation monad? Given is chainRec 's type chainRec...
Read more >
Option.ts - typed-fp
Option overview. Added in v0.9.2 ... chainRec. Constructor. struct. Typeclass. ChainRec; MonadRec ... export declare const chainRec: <A, B>( f: (value: A) ...
Read more >
sanctuary-type-classes | Yarn - Package Manager
The Fantasy Land Specification "specifies interoperability of common algebraic structures" by defining a number of type classes. For each type class, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found