Zulip Chat Archive

Stream: new members

Topic: Appling a function to itself


Fejfo (Nov 18 2023 at 18:53):

I noticed functions like def doTwice {α : Type} (f : α → α) (x: α) := f (f x) can be applied to themselves #check doTwice doTwice
Is there any way to type def doSelf (f : ?) := f f ?
def doSelf (f : ({α : Type u} → (α → α) → α)) := f f doesn't work. Why? (I've noticed {α : Type u} → (α → α) → α) : Type (u+1))

Kyle Miller (Nov 18 2023 at 18:59):

The type of doTwice seems to be {α : Type} → (α → α) → α → α, not {α : Type} → (α → α) → α

Kyle Miller (Nov 18 2023 at 19:00):

If you fix the type of f in doSelf, then it almost works (you just need to tell it what to use for the implicit argument)

Yongyi Chen (Nov 18 2023 at 19:14):

This worked:

def doSelf (f : {α : Type*}  (α  α)  (α  α)) : (α  α)  (α  α) := f f
def doTwice (f : α  α) := f  f

#eval doSelf doTwice (.^2 :   ) 2

Yongyi Chen (Nov 18 2023 at 19:19):

Fun fact:

#eval doTwice doTwice doTwice doTwice Nat.succ 1

works and outputs 65537 while

#eval doTwice doTwice doTwice doTwice doTwice Nat.succ 1

causes Lean to crash!

Yongyi Chen (Nov 18 2023 at 19:33):

Another fun fact, this is a valid definition too:

def doSelf2 (f : {α : Type*}  α  α) : α  α := f f

but one can't apply it to doTwice because doSelf2 expects a family of functions α -> α for every type α, and doTwice is not such a family -- it's only a family of functions (α -> α) -> (α -> α), in other words, a family of functions α -> α only for those α which happen to be of type β -> β for some type β.

In fact I wonder if anyone can think of a family {α : Type*} → α → α besides id.

Kevin Buzzard (Nov 18 2023 at 19:39):

In Wadler's "theorems for free" paper he shows that in a certain kind of type theory, id is the only inhabitant of that type. However in Lean you can just make things like "if alpha = Nat then fun n \mapsto 37 else id"

Yongyi Chen (Nov 18 2023 at 19:57):

I did manage to do something like that!

import Mathlib.Tactic

def doSelf2 (f : {α : Type*}  α  α) : α  α := f f

noncomputable def g : {α : Type}  α  α := by
  intro α
  if h : α =  then
    subst h
    exact fun _ :  => 37
  else
    exact id

example : g 4 = 37 := by
  simp only [g, dite_eq_ite, ite_true]

example : doSelf2 g 4 = 37 := by
  have : (  )   := sorry
  simp [g, doSelf2, this]

I just have an issue with how to prove that (ℕ → ℕ) ≠ ℕ. Is that even provable in Lean?

Kevin Buzzard (Nov 18 2023 at 20:00):

If two types have different cardinalities then you can prove they're unequal in Lean (and if they don't then you can't). So here you're OK here because Nat -> Nat is uncountable and Nat is countable.

Joachim Breitner (Nov 18 2023 at 20:03):

(deleted)

Kyle Miller (Nov 18 2023 at 20:05):

@Joachim Breitner Type doesn't have decidable equality, so at least you can't write that if statement without the definition being noncomputable. (At least, I don't think you can.)

Yongyi Chen (Nov 18 2023 at 20:12):

Interesting!

example : doSelf2 g 4 = 37 := by
  have : (  )   := by
    apply_fun Cardinal.mk
    simp
    exact ne_of_gt Cardinal.aleph0_lt_continuum
  simp [g, doSelf2, this]

Joachim Breitner (Nov 18 2023 at 20:28):

That makes sense. I was expecting that eliminating into Type from something that feels Prop-y (Types themselves) would not work, but this is ”just” using classical logic to decide, so that's why it works?

Shreyas Srinivas (Nov 19 2023 at 02:28):

Kevin Buzzard said:

In Wadler's "theorems for free" paper he shows that in a certain kind of type theory, id is the only inhabitant of that type. However in Lean you can just make things like "if alpha = Nat then fun n \mapsto 37 else id"

The proof I have seen of this property relied on a very strong semantic model of system F types.

Shreyas Srinivas (Nov 19 2023 at 02:33):

I just checked the paper and it doesn't say anything about dependent types at all


Last updated: Dec 20 2023 at 11:08 UTC