Zulip Chat Archive

Stream: general

Topic: Tagged/Untagged Inductives


Mac (Sep 23 2021 at 02:25):

I am curious as to why is the following is not a more common pattern in functional programming languages:

inductive FoobarCore : (tag : Lean.Name)  Type
| foo : FoobarCore `FoobarCore.foo
| bar : FoobarCore `FoobarCore.bar

abbrev Foobar := Sigma FoobarCore

namespace Foobar

abbrev foo : Foobar := Sigma.mk _ FoobarCore.foo
abbrev bar : Foobar := Sigma.mk _ FoobarCore.bar

instance : Coe (FoobarCore ``FoobarCore.foo) Foobar := fun x => Sigma.mk _ x
instance : Coe (FoobarCore ``FoobarCore.bar) Foobar := fun x => Sigma.mk _ x
instance : CoeDep Foobar n (FoobarCore n.1) := n.2

end Foobar

(or a similar variant where tag is a Nat or Fin)

FoobarCore could be represented as a untagged union and Foobar as its tagged version while still keeping both type safe. This would also (I believe) more easily enable constructing subtypes of the union type.

Reid Barton (Sep 23 2021 at 11:44):

In Haskell (and I guess most other functional programming languages) types can only depend on things that aren't computationally relevant, usually other types. So FoobarCore has to be implemented as a tagged union because a function that matches on it learns about tag, which is in some sense already an argument of the function but not one that is accessible at runtime.


Last updated: Dec 20 2023 at 11:08 UTC