Skip to content

Enumeration #39

Description

@samhh

It's a common use case to want to enumerate members of a sum type. This probably warrants inclusion in this library, but in what shape?

In Haskell, for all-nullary constructors, this might look something like this (GHCi):

> data X = A | B | C deriving (Enum, Bounded, Show)
> [minBound..] :: [X]
[A, B, C]

I believe that whilst derived instances of Enum and Bounded have a predictable order with relation to the data type definition, this isn't guaranteed for all possible implementations nor would otherwise be unlawful.

We have some helpers in Unsplash web with these type signatures and usages:

// `ExactMatch`: https://github.com/Microsoft/TypeScript/issues/13298#issuecomment-468733257
declare const enumerateNullary: <A extends Sum.Member<string>>() => <B>(ks: ExactMatch<Tag<A>, B>) => Array<A>
Sum.enumerateNullary<Weather>()(['Sun', 'Rain']) == [Weather.mk.Sun(), Weather.mk.Rain()]

type Values<A extends Sum.AnyMember> = {
  readonly [B in A as Tag<B>]: Value<B>;
};
declare const enumerate: <A extends Sum.AnyMember>() => (xs: Values<A>) => Array<A>
Sum.enumerate<Weather>()({ Sun: null, Rain: 123 }) == [Weather.mk.Sun(), Weather.mk.Rain(123)]

Unlike in Haskell, we can produce an enumeration provided an associated value for each constructor of a non-all-nullary sum type.

Because we've made the design decision to first and foremost define our sums at the type level, we don't know the tags at runtime except when provided by the consumer. In this case that means providing us with an array or object of tags. Sums of all-nullary constructors can benefit from a shorthand definition as above, however by moving from object keys to an array of keys we lose a uniqueness guarantee on the input. Additionally ExactMatch is required to ensure every key is present at least once.

fp-ts has a Bounded typeclass, but no Enum, nor any helpers. Notably in fp-ts, unlike in Haskell, Bounded is a subclass of Ord.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions