Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: flatMap/chain and iterables #63

Closed
emmanueltouzery opened this issue Aug 22, 2018 · 3 comments
Closed

question: flatMap/chain and iterables #63

emmanueltouzery opened this issue Aug 22, 2018 · 3 comments

Comments

@emmanueltouzery
Copy link
Contributor

as you know, I'm writing the prelude.ts library, and now using your list library as a backing implementation for the Vector. I'm currently considering switching the prelude's flatMap implementation away from the current prelude.ts and also the current list behavior, I was wondering if you have a particular opinion about this behavior.

Currently list has:

export function flatMap<A, B>(f: (a: A) => List<B>, l: List<A>): List<B>

The change I'm contemplating for prelude.ts would be:

export function flatMap<A, B>(f: (a: A) => Iterable<B>, l: List<A>): List<B>

And prelude.ts has the same (and had the same before it switched to a list backend for the Vector). It turns out that scala, and also immutablejs are using the looser Iterable-based signature.

list and prelude.ts however have the tighter type-signature, and for list:

> list.toArray(list.chain(x=>list.list(1,2,3), list.list(1,2,3)))
[ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
> list.toArray(list.chain(x=>[1,2,3], list.list(1,2,3)))
[]

To be clear, I'm not asking you to modify list to work in that different way, I'm asking if you had a reflection on that topic and decided that the current list signature is better. For me, in prelude.ts, I was guided by the monadic bind type-signature, and it didn't occur to me to "loosen up" the type signature, which could have advantages and inconvenients, but now I started thinking about it, and I may, or may not, make that change.

@wishfoundry
Copy link

I think what your trying to do is reuse a classical OOP collection type, when what you might want is a functional type, e.g.:
https://github.com/fantasyland/fantasy-land#chain

interface Chain {
  // unfortunately, there's a lack of consensus on `chain` vs `flatMap` still...
  flatMap() {}
  chain() {} // same as above
  ap() {}
}
function flatMap<A>(f: (a:A) => Chain<B>, List<A>): List<B>

although I think most libs I've seend tend to give up and just:

function flatMap<A>(f: (a:A) => List<B>, List<A>): List<B>

@emmanueltouzery
Copy link
Contributor Author

yes good point, what did fantasyland decide, and they decided like list and the current prelude.ts (and unlike scala & immutablejs), it's clearly written:

  • f must return a value of the same Chain

(f being the callback which is passed in to flatMap/chain)

on the one hand this accepting an Iterable is 'handy', on the other hand it feels a little like Promise.then which mixes up map & flatMap in a single 'then' function. From that point of view the current behavior is better. Still thinking about it though ;)

@emmanueltouzery
Copy link
Contributor Author

Closing. List has its system and obviously doesn't intend to change. I'm also not going to change it for prelude.ts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants