Zulip Chat Archive

Stream: lean4

Topic: When does Repr not work?


Chris Lovett (Jun 20 2022 at 23:54):

I know Leo explained this to me before but I'm still confused why Repr doesn't work on Option:

inductive Option (α : Type) : Type where
  | none : Option α
  | some (val : α) : Option α
  deriving Repr

/-
expression
  Option.none
has type
  Option ?m.704
but instance
  Lean.Eval (Option ?m.704)
failed to be synthesized, this instance instructs Lean on how to display
the resulting value, recall that any type implementing the `Repr` class
also implements the `Lean.Eval` class
-/
#eval Option.none

#eval Option 10  -- this works fine and prints "some 10" so why can't Option.none print "none" ?

So when can I expect Repr to fail like this? Any time there is an unresolved metavariable? Could Repr be specialized in this case so that it prints "none" since the metavariable does not need to be resolved in that case?

Mario Carneiro (Jun 21 2022 at 00:13):

You would need that unresolved metavariable to have a Repr instance to be able to print "none"

Mario Carneiro (Jun 21 2022 at 00:15):

I don't think we should try to evaluate terms containing free variables in #eval

Mario Carneiro (Jun 21 2022 at 00:16):

I would suggest just writing (none : Option Nat) or whatever

Mario Carneiro (Jun 21 2022 at 00:16):

or @none Nat if you prefer

Mario Carneiro (Jun 21 2022 at 00:18):

Even if the type did have a repr instance unconditionally you will get a different error:

inductive Foo (α : Type)
| foo : Foo α

instance : Repr (Foo α) := λ _ _ => "Foo"

#eval Foo.foo
-- don't know how to synthesize implicit argument
--   @Foo.foo ?m.168
-- context:
-- ⊢ Type

Mac (Jun 21 2022 at 00:55):

A more Rust-like way for this to work, would be to instead export none from a singleton None type that is coercible to Option. For example:

namespace Alt

inductive None
| none
deriving Repr

export None (none)

instance : Coe None (Option α) := fun _ => Option.none

#eval none --- Alt.None.none
#eval (none : Option Nat) -- none

Mac (Jun 21 2022 at 00:58):

Such a flexible None type could also coerce to other types with null constructors (e.g. List):

instance : Coe None (List α) := fun _ => List.nil

Alternatively, Unit/PUnit could be use for this purpose instead rather than creating a new type.


Last updated: Dec 20 2023 at 11:08 UTC