Zulip Chat Archive

Stream: new members

Topic: inductive type with anonymous constructors


Vaibhav Karve (Feb 06 2020 at 20:56):

I want to translate the following English sentence into Lean:
"An extended bool is either a value called extra or a boolean value".

Normally I would do it by typing

inductive extended_bool : Type
| extra   : extended_bool
| boolean : bool  extended_bool

However, this means that when working with extended bool, I always need to destruct it and include the boolean constructor for the boolean case. Can I save myself some work by having an "anonymous" constructor? Is this considered bad coding practice?

Mario Carneiro (Feb 06 2020 at 21:00):

That looks like option bool to me

Mario Carneiro (Feb 06 2020 at 21:01):

Anonymous constructors unfortunately only work for types with one constructor

Vaibhav Karve (Feb 06 2020 at 21:14):

But even with option, don't I have to use some and none? I wanted some way to say "if it is not extra, then it must be boolean, so I am not going to write it."

Another example might be bool ⊕ nat. Is there a way for me to define functions on this type without constantly making references to sum.inl and sum.inr? As in, can Lean infer the definition of the function simply from the type of the arguments?

Patrick Massot (Feb 06 2020 at 21:15):

You can define a coercion from bool to extended_bool

Patrick Massot (Feb 06 2020 at 21:17):

def ebool := option bool

instance : has_coe bool ebool := ⟨λ b, some b

variable f : ebool  ebool

#check f tt
#check f none

Patrick Massot (Feb 06 2020 at 21:17):

Is that what you want?

Patrick Massot (Feb 06 2020 at 21:20):

In case this is not clear, option bool without wrapping it already gives you that.

Mario Carneiro (Feb 06 2020 at 21:27):

option actually already has such a coercion

Mario Carneiro (Feb 06 2020 at 21:27):

(oops, patrick already said this)

Mario Carneiro (Feb 06 2020 at 21:29):

This will work in cases like bool ⊕ nat, with type based dispatch, but it won't work in patterns (i.e. pattern matching requires explicit inl and inr). But I don't think it is good style, and the option coe is rarely used in mathlib

Vaibhav Karve (Feb 06 2020 at 21:52):

@Patrick Massot yes, that is what I was looking for. That's a cool trick with has_coe.
@Mario Carneiro Yes, I can see how this can lead to smelly code. I'll try and avoid this kind of usage in practice.

For the case of bool ⊕ nat, do I still need explicit coercion? I am not sure I understand what you mean by type-based-dispatch. So far I have:

def ebool := bool  nat

def f : ebool  nat   -- throws an error
| tt := 1
| ff := 0
| n  := n

How can I define that f properly?

Mario Carneiro (Feb 06 2020 at 21:58):

like I said, it won't work in patterns

Mario Carneiro (Feb 06 2020 at 22:00):

def ebool := bool  nat

instance coe_l : has_coe bool ebool := sum.inl
instance coe_r : has_coe nat ebool := sum.inr

example : ebool := tt
example : ebool := ff
example (n : nat) : ebool := n

Mario Carneiro (Feb 06 2020 at 22:02):

Oh, it looks like this works too:

def f : ebool  nat
| tt := 1
| ff := 0
| (n : ) := n

Vaibhav Karve (Feb 06 2020 at 22:05):

Oh, that's just perfect! Thanks. :+1:


Last updated: Dec 20 2023 at 11:08 UTC