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

Sum types? #411

Open
Kmeakin opened this issue Nov 8, 2022 · 4 comments
Open

Sum types? #411

Kmeakin opened this issue Nov 8, 2022 · 4 comments

Comments

@Kmeakin
Copy link
Contributor

Kmeakin commented Nov 8, 2022

Fathom currently has anonymous product types (records), but no (convenient) way of expressing sum types.

Potential solutions

  • Do nothing. Encode sum types as dependent records (eg let Option : Type -> Type = fun T => {tag : Bool, value : if tag then T else {})
  • Anonymous sum types, dual to records: (eg let Option : Type -> Type = fun T => sum {None : {}, Some : T})
  • Algebraic data types a la Haskell, ML, Rust etc
  • Polymorphic variants

Design considerations

  • Are they ergonomic to use?
  • Can they express recursion?
  • Can they be compiled efficiently?
  • Nominal or structural?
  • Row polymorphism?
  • First class labels?

Prior Art

  • (Generalized) Algebraic data types: Haskell, Agda, Coq, Idris, Ocaml
  • Anonymous sum types: Haskell, Dhall
  • Polymorphic variants: Ocaml
@eashanhatti
Copy link

eashanhatti commented Nov 8, 2022

Another consideration is recursive types! If sum types are not anonymous then things become a lot easier, but if they're anonymous it gets tricky. In the latter case, maybe you could use isorecursive types and insert roll and unroll during elaboration?

@brendanzab
Copy link
Member

At one stage I was thinking you could add an structural enum type:

enum { l₁, ..., lₙ } : Type

       lₘ ∈ { l₁, ..., lₙ }
────────────────────────────────
 enum lₘ : enum { l₁, ..., lₙ } 

  e : enum { l₁, ..., lₙ }      t₁ : t  ...  t₁ : tₙ
─────────────────────────────────────────────────────
  match e { enum l₁ => t₁, ..., enum lₙ => tₙ } : t

Which could be used for the tags of records. This is a bit like Martin Löf’s finite sets (I think?). I was also thinking that there would be some corresponding format for enums as well. In this case we’d need some syntactic sugar or elaborator support to make tagged unions bearable if we went that route. I’d also imagine that it would require us to implement dependent pattern matching on records (which we don’t yet do). And yeah recursive types, and mutually recursive types could be… fun?

We already have top level items so maybe it would be easier to go with top level tagged union declarations like Haskell, OCaml, Rust? Save the experimentation for another time and place?

@brendanzab
Copy link
Member

brendanzab commented Nov 9, 2022

IIRC Mini-TT had some simple form of tagged union that might be interesting to look at.

@brendanzab
Copy link
Member

I think one thing that might help in terms of design is thinking in terms of how this might help us with binary data descriptions. Eg. Looking through the OpenType data description, where would tagged/disjoint unions help us. And also make us think about how we might have corresponding formats that might produce these tagged unions.

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