Zulip Chat Archive

Stream: new members

Topic: Is there a way to use inductive variants as types?


Alok Singh (Jan 15 2025 at 17:23):

Morally, I want to do this:

inductive Test where
| a
| b

-- doesn't work, but is what I want
def test (x: Test.a) : Test.b :=
  match x with
  | .a => .b

-- works, but slightly unsatisfying
def test (x: Test) (h: x = Test.a) : Test :=
  match x with
  | .a => .b

nrs (Jan 15 2025 at 18:29):

inductive TestIndexer | a | b

inductive Test : (α : TestIndexer) -> Type
| mk : (x : TestIndexer) -> Test x

nrs (Jan 15 2025 at 18:31):

example : Test .a -> Test .b := fun t => match t with | .(.mk .a) => .mk .b

nrs (Jan 15 2025 at 18:32):

.(.mk .a) is used because you are matching on an inaccessible pattern determined by the type of your function

Mitchell Lee (Jan 15 2025 at 18:38):

What do you want x: Test.a to mean?

Kyle Miller (Jan 15 2025 at 18:39):

Here's a hack with coercions, assuming the meaning is "a value as a type should be the subtype with just that value":

inductive Test where
  | a
  | b

instance : CoeSort Test Type where
  coe v := { x : Test // x = v }

instance (v : Test) : CoeDep Test v v where
  coe := v, rfl

def test (x: Test.a) : Test.b :=
  match x with
  | Test.a => Test.b

nrs (Jan 15 2025 at 18:41):

@Mitchell Lee most likely they mean to enforce type-level values of an arbitrary finite type

Mitchell Lee (Jan 15 2025 at 18:42):

Why would you want to define a function that only has one possible input?

nrs (Jan 15 2025 at 18:42):

it is a simpler case of a function that only takes 2, 3, 4, (etc.) inputs and no more

Mitchell Lee (Jan 15 2025 at 18:43):

By "only one possible input" I mean that the variable x can only take one possible value.

nrs (Jan 15 2025 at 18:45):

in this case yes but it is instructive to understand how this works to make more general cases (it is also usually something beginners will be confused about, the fact that any finite type is type-theoretically "the same" (through the equivalence to the canonical finite type of that same size)), so it is instructive to see how limiting the actual implementation is

Kyle Miller (Jan 15 2025 at 18:47):

I don't think we should assume that Test is supposed to be an enumeration like this in the actual application. Possibly Alok wants a version that supports subtypes-per-constructor, which my hack doesn't handle.

Mitchell Lee (Jan 15 2025 at 18:49):

In that case, I would suggest using the parameters of the constructor as the parameters of your function, rather than using a subtype

Alok Singh (Jan 15 2025 at 20:39):

the motivation for this was https://github.com/rust-lang/rfcs/pull/1450 and typescript's type narrowing


Last updated: May 02 2025 at 03:31 UTC