Zulip Chat Archive

Stream: new members

Topic: Typeclass constraints


Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:14):

I am trying to convert a parser combinator tutorial in lean4 the following haskell code has Eq as the typeclass constraint passed as an argument is there a way to write an equivalent in lean4?

pSym :: Eq s ⇒ s → Parser s s
pSym a = P (λinp → case inp of
(s : ss) | x ≡ a → [(s, ss)]
5
otherwise → [ ]
)

in lean

def pSym (a : Eq s) : s -> Parser s s :=
  Parser.P (λ inp =>
    match inp with
    | s :: ss => if Eq.refl a s then [(s, ss)] else []
    | _ => [])

but this is incorrect, the error is

error: type expected, got
  (Eq s : ?m.911 → Prop)

Yaël Dillies (Mar 23 2024 at 20:15):

What's the type of s in the Haskell code?

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:16):

There isn't, I think to make it generic

Yaël Dillies (Mar 23 2024 at 20:16):

Are you sure s isn't the type?

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:17):

it is but there is no concrete type

Yaël Dillies (Mar 23 2024 at 20:17):

... in which case you can just remove that Eq s argument since the Lean type s will automatically have access to = notation (docs#Eq is defined for all types)

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:20):

Ok but pSym in the haskell code consumes a type with identifier a and returns a function of type s -> Parser s s if I remove Eq s then I just pass a without any explicit types?

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:21):

something like this

def pSym a : s -> Parser s s :=
  Parser.P (λ inp =>
    match inp with
    | s :: ss => if a = s then [(s, ss)] else []
    | _ => [])

Yaël Dillies (Mar 23 2024 at 20:21):

The Lean version should be of the form pSym {s : Type} : s → Parser s s (for some definition of Parser)

Yaël Dillies (Mar 23 2024 at 20:21):

Note that the Haskell code is using s for two different things!

Yaël Dillies (Mar 23 2024 at 20:22):

s refers to both a type and an element of that type

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:22):

Oh thanks!

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:25):

do we also need to define an instance of Decidable? because it is unable to generate Decidable (a = s) instance

Timo Carlin-Burns (Mar 23 2024 at 20:25):

You might need [DecidableEq s] for the if

Yaël Dillies (Mar 23 2024 at 20:25):

Just assume [DecidableEq s]

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:29):

def pSym {s : Type} [DecidableEq s] (a : s) : s -> Parser s s :=
  Parser.P (λ inp =>
    match inp with
    | s :: ss => if a = s then [(s, ss)] else []
    | _ => [])

is the above code correct? if I place [DecidableEq s] before the {s : Type} I get the same error, right now I am getting a different error where lean compiler errors out with

error: type mismatch
  Parser.P fun inp =>
    match inp with
    | s_1 :: ss => if a = s_1 then [(s_1, ss)] else []
    | x => []
has type
  Parser s s : Type
but is expected to have type
  s → Parser s s : Type

Yaël Dillies (Mar 23 2024 at 20:33):

What's Parser.P? Can you provide a #mwe ?

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:33):

yep, just a sec

Yaël Dillies (Mar 23 2024 at 20:34):

Wait, actually, the error is easy to spot

Yaël Dillies (Mar 23 2024 at 20:34):

You meant either (a : s) : Parser s s := or : s -> Parser s s := fun a ↦, but not both

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:35):

inductive Parser (s t : Type u) : Type u :=
  | P : ParserType s t -> Parser s t

this is how I have defined it, in the tutorial

newtype Parser s t = P ([s ] → [(t, [s ])])

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:36):

Yaël Dillies said:

You meant either (a : s) : Parser s s := or : s -> Parser s s := fun a ↦, but not both

I wanted the former, usually in haskell or ML like languages one can assume both, I am not sure that is correct in lean

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 20:37):

ParserType is just abbrev ParserType s t := List s -> List (Prod t (List s))

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 21:04):

is there something wrong in the assumptions I've made?

Yaël Dillies (Mar 23 2024 at 21:05):

Yaël Dillies said:

You meant either (a : s) : Parser s s := or : s -> Parser s s := fun a ↦, but not both

Did you understand my message above? :point_up:

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 21:09):

The only difference I know is that it's syntactic sugar but I'm sure it's wrong and I have missed something

Yaël Dillies (Mar 23 2024 at 21:09):

Simply change your code to

def pSym {s : Type} [DecidableEq s] (a : s) : Parser s s :=
  Parser.P (λ inp =>
    match inp with
    | s :: ss => if a = s then [(s, ss)] else []
    | _ => [])

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 21:12):

I'm sorry, I'm such a big idiot, thanks for helping a fool! :man_facepalming:

Shubham Kumar 🦀 (he/him) (Mar 23 2024 at 21:12):

it was right there, I couldn't see it

Yaël Dillies (Mar 23 2024 at 21:13):

No problem :smile:

Eric Wieser (Mar 23 2024 at 21:43):

if I place [DecidableEq s] before the {s : Type} then ...

I strongly recommend adding set_option autoImplicit false to the top of your file so that this gives a much stronger error messag


Last updated: May 02 2025 at 03:31 UTC