Zulip Chat Archive

Stream: lean4

Topic: anonymous structure types


Anders Christiansen Sørby (Apr 07 2022 at 10:25):

Is it possible do define anonymous structure type syntax with the current system?
For example

structure Any := (type : Type ) (val : type)
inductive Struct | MyCons {a: A, b : B}
-- And
def f : Struct -> Any
  | MyCons { a, b} => {val := a, type := A}

Which is closer to Haskell syntax.

Mario Carneiro (Apr 07 2022 at 12:35):

You can do this:

structure Any := (type : Type ) (val : type)
inductive Struct | mk (a: A) (b : B) : Struct

def f : Struct -> Any
  | a, b => {val := a, type := _}

Mario Carneiro (Apr 07 2022 at 12:36):

I don't see why we should support multiple syntaxes for the same thing, beyond what lean already supports vis-a-vis moving arguments across the colon and structure / inductive

Leonardo de Moura (Apr 07 2022 at 13:46):

Here are other alternatives:

structure Any where
  type : Type
  val  : type

structure Struct where
   myCons :: -- You can give your own name to the structure constructor
     a : Nat
     b : Bool

def f₁ : Struct -> Any
  | { a, b } => { val := a } -- We don't need to provide `type`

def f₂ : Struct -> Any
  | .myCons a b => { val := a } -- The namespace at `.myCons` is inferred by Lean

def f₃ : Struct -> Any
  | Struct.myCons a b => { val := a }

inductive Struct' where
  | myCons (a : Nat) (b : Bool)

-- You cannot use the structure instance notation with inductive datatypes
-- even if they have only one constructor
-- def f₄ : Struct' -> Any
--  | { a, b } => { val := a }

def f₅ : Struct' -> Any
  | .myCons a b => { val := a }

def f₆ : Struct' -> Any
  | Struct'.myCons a b => { val := a }

Anders Christiansen Sørby (Apr 08 2022 at 08:03):

Why doesn't this work:

structure Struct where
   myCons ::
     a : Nat
     b : Bool
  myOtherCons ::
     a : Nat
     b : Bool

Would be really nice to do this. Rust and Haskell supports it.

Sebastian Ullrich (Apr 08 2022 at 08:10):

The point of a structure is that is has exactly one constructor, and this is true in Rust and Haskell as well. Basically all the special syntax for structures is dependent on this property. I assume you you are referring to struct-like enums in Rust; I'm not sure what you're referring to in Haskell. It's always a good idea to make these things explicit in a proposal, and in particular to mention actual advantages and use cases.

Anders Christiansen Sørby (Apr 08 2022 at 08:38):

Yes. I'm thinking of the struct like enums in rust (I guess haskell only has them for single constructors). So my suggestion would be something like

inductive EnumStruct | myCons {a: A, b : B} | myOtherCons {a : A, c: C}
open
def m : EnumStruct -> A
 | .myCons { a, b } => a
 | .myOtherCons { a, c } => a

But another use of anonymous structure types could be to pattern match select a class of structures that has some particular fields

structure SA :=
  a : A
  b : B

structure SB :=
  a : A
 c : C

-- Which would implicitly define a class something like this
-- Which is a Lens I guess
class HasField (name: Name) (F : Type) (A : Type) where
  getField : A -> F
  putField : A -> F -> A

instance : HasField (@a) A SA := -- SA.a ...
instance : HasField (@a) A SB := -- SB.a ...

-- which can then be used as a normal structure type
def act (s : { a : A }) : A := s.a

This could be a part of adding Lenses and optics if that is something you are looking into.

Sebastian Ullrich (Apr 08 2022 at 08:40):

I'm not sure if HasField makes sense in Lean. We don't have global field names like in Haskell.

Sebastian Ullrich (Apr 08 2022 at 08:42):

And Lean is a completely nominal language like Rust and Haskell, I really don't think there will be any structural typing

Anders Christiansen Sørby (Apr 08 2022 at 08:42):

What do you think about adding lenses?

Anders Christiansen Sørby (Apr 08 2022 at 08:47):

I think adding lenses / optics would be even more powerful. If one could have some short hand syntax for indicating that a particular lens instance would be present s : { a : A } would mean {S : Type u} [Lens S A] (s : S)

Sebastian Ullrich (Apr 08 2022 at 08:52):

I don't think it's likely that this will end up in Lean itself, but of course extensibility is the whole point of Lean 4! We currently lack some kind of "binder macros" for doing something like that, but it's a topic that has come up before.

Anders Christiansen Sørby (Apr 08 2022 at 08:55):

I've done some preliminary work to add lenses in lean. Although I'm not sure type classes is the correct tool. Lenses have to be first class

def Lens (a b s t : Type u) : Type u := Para [] [] a b s t

def Lens' (s a : Type u) : Type u := Lens s s a a

I've based this on Agda which has a lot of good lens libraries.
This is particularly useful when doing more practical software engineering. Probably not so useful for pure math except perhaps category theory (but they would probably define their own syntax anyway)?


Last updated: Dec 20 2023 at 11:08 UTC