Zulip Chat Archive
Stream: lean4
Topic: Infer Sum.inl or Sum.inr
Ian Riley (Oct 22 2023 at 18:59):
Hey everyone! I was playing around with a few different ways to manipulate lists of numbers in a generic way. The approach I took this morning was to look at using a Sum type since I haven't used the Sum type much. I was very surprised to find out that Lean can't infer that a value whose type is a member of a Sum type is itself an element of that Sum type. For example, this was not allowed:
def List.sum (xs : List (Sum Nat Int)) : (Sum Nat Int) := sorry
def l := [1, 2, 3, 4]
#eval List.sum l
I apologize if some of that is a bit off. I was using the unicode symbols in my editor. I do have a working implementation of List.sum that I can post if need be. Anyway, I had to change it to:
def l := [Sum.inl 1, Sum.inl 2, Sum.inl 3, Sum.inl 4]
I did try other permutations and explicit types. All resulted in the same thing. Is there anyway that I can have lean infer that 1 : Nat is a valid element when the input type is Sum Nat Int?
Arthur Adjedj (Oct 22 2023 at 19:22):
You can use coercions for that:
instance : Coe A (Sum A B) := ⟨Sum.inl⟩
instance [Coe A B] : Coe (List A) (List B) where
coe x := x.map Coe.coe
def List.sum (xs : List (Sum Nat Int)) : (Sum Nat Int) := sorry
def l := [1, 2, 3, 4]
#check List.sum l --no type error
Ian Riley (Oct 22 2023 at 20:20):
Nice! Thank you. It doesn't work for literals, but I was able to follow the same pattern to get literals working.
instance : OfNat (Sum Nat Int) x where
ofNat := Sum.inl x
However, I can't seem to get negative literals to work.
Ian Riley (Oct 22 2023 at 21:01):
It also seems counter intuitive to have literals work differently in this context than definitions, especially since there’s very little visibility when using check. I think people would naturally expect that if I check [1,2,3,4] and it comes back as List Nat and if I define list := [1,2,3,4], which also checks as a List Nat, that if the latter works under type coercion, then the former would too. But that’s not the case.
Ian Riley (Oct 22 2023 at 21:53):
Got it! I was trying to use Neg like Nat or like OfNat. Then it dawned on me that it might work more like Coe. Sure enough, this works.
instance : Neg (Sum Nat Int) where
neg x := match x with
| Sum.inl x => Sum.inr (-x)
| Sum.inr x => Sum.inr (-x)
I do appreciate all the help! I also want to say that any criticisms I may add are only because I want Lean to do really well.
Last updated: Dec 20 2023 at 11:08 UTC