gcanti / flow-static-land

[DEPRECATED, please check out fp-ts] Implementation of common algebraic types in JavaScript + Flow
MIT License
408 stars 22 forks source link

Add support for chainRec #35

Closed gcanti closed 7 years ago

gcanti commented 7 years ago

https://github.com/rpominov/static-land/blob/master/docs/spec.md#chainrec

gcanti commented 7 years ago

@rjmk I'm reading the spec for chainRec and is rather confusing. This signature is quite criptic

chainRec :: ChainRec m => ((a -> c, b -> c, a) -> m c, a) -> m b

with respect to

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

I have read the relevant issues in fantasy-land (https://github.com/fantasyland/fantasy-land/issues/151, https://github.com/fantasyland/fantasy-land/pull/152) and the best explanation is this comment https://github.com/fantasyland/fantasy-land/pull/152#issuecomment-244566047.

Now I understand the benefits of not depending on a particular implementation of Either but why fantasy-land / static-land doesn't provide a spec for Either in the first place? (<= not sure if it has been already discussed somewhere)

Since flow-static-land contains an implementation of Either it seems weird and confusing for the users not using it and implementing the first signature instead.

cc @rpominov

rpominov commented 7 years ago

why fantasy-land / static-land doesn't provide a spec for Either in the first place? (<= not sure if it has been already discussed somewhere)

I think initially the idea of fantasy-land was to provide specification for type classes and not for concrete types. Maybe you're right and it would be a good idea to add specifications for concrete types like Either. I'm also not sure if it was discussed before, if you want to discuss you should open an issue in fantasy-land repo (static-land just translates what is in fantasy-land to static methods approach currently).

gcanti commented 7 years ago

I think initially the idea of fantasy-land was to provide specification for type classes and not for concrete types

It was my guess too. And it worked well, as long as the definitions don't involve concrete types. But ChainRec raises a problem. Unfoldable is even worse (Maybe AND Tuple):

class Unfoldable t where
  unfoldr :: forall a b. (b -> Maybe (Tuple a b)) -> b -> t a

Moreover it's a shame that we have great libraries out there for Maybe, Either, Task but there is no standard for them

if you want to discuss you should open an issue in fantasy-land repo

Yeah, good idea. I'll do a deeper search in the fantasy-land repo before submitting.

gcanti commented 7 years ago

static-land just translates what is in fantasy-land to static methods approach currently

@rpominov actually when I first encountered static-land my first thought was that it was strictly more expressive than fantasy-land. For example I don't see how to encode in fantasy-land the following two monoids

without modifying the Number constructor or the Number prototype (or wrap the numbers in a class). Moreover I can't encode them at the same time, so I must make an arbitrary choice which I find too limiting. What I mean is that, even if fantasy-land is more handy because of the chainable APIs, static-land is theoretically more powerful. From e theoretical point of view I see fantasy-land as a special case of static-land, not the other way around.

TL;DR static-land ❤️

rpominov commented 7 years ago

Yea, I also think that static-land can be more expressive. But when it comes to changes like introducing new algebras and such it just feels too scary for me to diverse from fantasy-land, because I'm still learning and have little experience with all this stuff to be honest.

Also another benefit of having two spec match close to each other is that when people learn one of them they automatically learn the other.

gcanti commented 7 years ago

@rjmk I'm not convinced by the signature in the specification, for the moment I'm going to support the PureScript signature

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