Conversation

by contrast, the judgement for a (strict) pair (written ⊗) works a little differently; we’ll look at the elim rule (for reasons that are unlikely to be obvious), with proof terms: Γ ⊢ x : Y ⊗ Z Γ, y : Y, z : Z ⊢ b : C ---- Γ ⊢ case x of (y, z) -> b : C
1
here again we have assumptions, but since they’re present for elimination, that means they’re eager—this is a redex, so we have to have the values of y and z ready to do anything with it. by contrast, good ol’ ✕ is eliminated by a pair of projections, neither of which extends Γ
1
the other part of this distinction is that a datatype constructor is not a function. Haskell (among others) conveniently introduces functions with the same name as the constructor so that you can write Foo x y where Foo is ternary and get a function Z -> Foo, but…
1
…the actual datatype constructor has to be fully saturated or not at all. (in Facet I do this by just synthesizing constructor _functions_ when I elaborate the datatype declaration.)
1
so that can make the space a little weirder if you have both record-style construction syntax and function-style construction syntax for records, like Haskell does, i.e. Foo { a = x, b = y, c = z } and Foo x y z
1
1
keyword args have a lot to recommend them tho yeah I recall us chatting about some of the challenges in a DT setting. tbh I feel like the ergonomic issues with DTs undermine their utility for non-proof-assistant stuff :\
1
1
Yeah that's kind of why I want to focus on using them for non-proof-assistant stuff. As an expressive programming system for working with types, terms, and modules in a unified language. but yeah there are indeed annoyances.
1
1