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

NonEmptyList #70

Open
grossbart opened this issue Sep 24, 2018 · 7 comments
Open

NonEmptyList #70

grossbart opened this issue Sep 24, 2018 · 7 comments

Comments

@grossbart
Copy link

I used funkia/list on a larger project and was generally very happy with it. One big missing piece for me was the availability of a NonEmptyList. Having this available helps reduce a lot of code concerned with checking if a list is empty or not, because in many situations an empty list would be an application error and should be caught far out in the API layer, not in the app's core code.

The fp-ts NonEmptyArray is a good starting point for how this should work.

@paldepind
Copy link
Member

I'm happy to hear that you've enjoyed using List 😄

Adding a NonEmptyList is something that I've been considering and something that I think would be very useful. However, I can see two different ways to implement it, and I'd like to hear what you think about them:

1/ Make NonEmptyList s a seperate from List and create a different version of relevant functions that only takes NonEmptyLists. This is what I've seen done in languages like Haskell and PureScript.
2/ Make NonEmptyList a subtype of List. Then every function that accepts a List also accepts a List. But the type of relevant functions would change. For instance append would return a NonEmptyList and head would be overloaded with the type

function head<A>(l: NonEmptyList<A>): A;
function head<A>(l: List<A>): A | undefined;

My current thoughts are that the latter approach the best fit for TypeScript. The major downside seems to be that the types of various function will be more complicated to handle NonEmptyLists as well.

What do you think?

@grossbart
Copy link
Author

I was thinking way too long about this, there's always a con that crops up when you have so many pros for one or the other way 😅 In the end, I think your suggestion 2 makes the most sense for this library: it's a self-contained library that has the luxury to know all the types it needs to work with and can therefore provide functions that know how to deal with either List or NonEmptyList.

@paldepind
Copy link
Member

@grossbart Thank you for the feedback. It's the option I'm leaning towards as well. This shouldn't be too tricky to add. I'll work on it when I get the time and do a PR.

@joshburgess
Copy link

joshburgess commented Jan 6, 2019

FWIW, fp-ts follows approach 1, mimicking what languages like Haskell & PureScript do:

https://github.com/gcanti/fp-ts/blob/master/src/NonEmptyArray.ts

I like this, because it keeps the two types totally isolated and distinct from each other.

EDIT: Whoops, didn't notice NonEmptyArray from fp-ts was linked at the top already. 😁

@grossbart
Copy link
Author

@joshburgess I know they separate the two completely, but I don't have the intuitions yet to decide whether combining them for this library would mean trouble. My reasoning was that because this library is self-contained it couldn't hurt to have NonEmptyList be a subtype of List with an additional constraint. But maybe this is a fallacy and we trade comfort at the expense of lawfulness? I can certainly see that keeping them separate makes it more clear that they are different things (even though they seem so similar at first glance).

@joshburgess
Copy link

joshburgess commented Jan 8, 2019

What about, instead of subtyping, just importing and using the utility functions from List also with NonEmptyList and casting? (internally only, I mean)

I'm no fan of casting, in general, but it would be only be an internal implementation detail. With this approach, it would allow reusing the existing code + making maintainability for the two separate list types easier, but would still be type-safe from the outside, requiring the user to use the proper types in their app code.

Just an idea. I would probably resort to something like that, I think... to cut down on maintenance costs, but also try to control how people use the API.

Then again, some utility functions for List might not really apply to NonEmptyList since the possibility of the list being empty is no longer there (this would change the implementation for some functions).

@paldepind
Copy link
Member

@joshburgess

What about, instead of subtyping, just importing and using the utility functions from List also with NonEmptyList and casting? (internally only, I mean)

That sounds interesting. But, I don't fully understand what you're proposing here? Could you maybe explain it in more detail?

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

3 participants