fp-ts icon indicating copy to clipboard operation
fp-ts copied to clipboard

Support for NonEmptySet

Open CYBAI opened this issue 5 years ago • 7 comments

🚀 Feature request

There's NonEmptyArray in fp-ts though, there's no NonEmptySet for now.

In a private project, I use NonEmptySet in back-end side so I would hopefully use a same type in front-end.

However, currently, we only have NonEmptyArray and Set in fp-ts. If I use NonEmptyArray, the type itself will not have the unique item ability. But if I use Set, then I can't see the value is actually non-empty.

Current Behavior

Only having NonEmptyArray.ts or Set.ts

Desired Behavior

Having NonEmptySet.ts

Suggested Solution

Adding NonEmptySet type

Who does this impact? Who is this for?

All users

Describe alternatives you've considered

Here's a possible alternative

pipe(
  myNonEmptySet,
  Set.toArray(eqString),
  NonEmptyArray.fromArray,
)

but as I described in feature request, for now,

if I'd like to represent the NonEmpty part, I can only use NonEmptyArray but it will lose the representation of Set.

if I'd like to represent the Set part, I can only use Set but it will lose the representation of NonEmpty

Additional context

N/A

Your environment

Software Version(s)
fp-ts 2.5.1
TypeScript 3.7.5

CYBAI avatar Apr 24 '20 06:04 CYBAI

Adding NonEmptySet type

@CYBAI what's the definition of the NonEmptySet type?

gcanti avatar Apr 24 '20 08:04 gcanti

Adding NonEmptySet type

@CYBAI what's the definition of the NonEmptySet type?

Hi @gcanti ! I would expect a NonEmptySet will always at least hold one item which is similar to NonEmptyArray.

Also, because it's a NonEmpty Set, so I would expect it works like a Set which means it won't allow duplicated items.

Hope this will answer your question 🙏 Thanks!

CYBAI avatar Apr 24 '20 09:04 CYBAI

I mean the actual definition of NonEmptySet as TypeScript code. How do you represent a non empty Set using the type system?

gcanti avatar Apr 24 '20 09:04 gcanti

@CYBAI We can define NonEmptyArray as

export interface NonEmptyArray<A> extends Array<A> {
  [0]: A
}

I think it's impossible to do the same for Set because it has no index access (there's no way to defined required [0] field).

raveclassic avatar Apr 24 '20 10:04 raveclassic

What about defining it using a brand type? Then it could only be created using the constructors from the NonEmptySet module but once you have done that you know that you have a NonEmptySet.

For example:

export type NonEmptySet<A> = Set<A> & {
  readonly NonEmptySet: unique symbol
}

cdimitroulas avatar Mar 27 '21 18:03 cdimitroulas

It would have to be a ReadonlyNonEmptySet in order for the brand to remain accurate over the lifetime of the object. I'm not sure that sets can be marked as readonly in TS/JS

EricCrosson avatar Apr 06 '21 12:04 EricCrosson

The problem with branded types is that they are not offically supported by TypeScript and there's no standard solution.

A general (constructive) solution would be a higher kinded data type: PureScript NonEmpty

gcanti avatar Apr 06 '21 14:04 gcanti