Based on the discussion at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/for.2C.20unexpected.20need.20for.20type.20ascription/near/269083574 The consensus seemed to be that "auto pure" is more confusing than its worth.
200 lines
4 KiB
Text
200 lines
4 KiB
Text
def f (x : Nat) : IO Nat := do
|
||
IO.println "hello world"
|
||
let aux (y : Nat) (z : Nat) : IO Nat := do
|
||
IO.println "aux started"
|
||
IO.println s!"y: {y}, z: {z}"
|
||
pure (x+y)
|
||
discard <| aux x
|
||
(x + 1) -- It is part of the application since it is indented
|
||
discard <| aux x (x -- parentheses use `withoutPosition`
|
||
-1)
|
||
discard <| aux x x;
|
||
aux x
|
||
x
|
||
|
||
#eval f 10
|
||
|
||
def g (xs : List Nat) : StateT Nat Id Nat := do
|
||
let mut xs := xs
|
||
if xs.isEmpty then
|
||
xs := [← get]
|
||
dbg_trace ">>> xs: {xs}"
|
||
return xs.length
|
||
|
||
#eval g [1, 2, 3] |>.run' 10
|
||
#eval g [] |>.run' 10
|
||
|
||
theorem ex1 : (g [1, 2, 4, 5] |>.run' 0) = 4 :=
|
||
rfl
|
||
|
||
theorem ex2 : (g [] |>.run' 0) = 1 :=
|
||
rfl
|
||
|
||
def h (x : Nat) (y : Nat) : Nat := Id.run <| do
|
||
let mut x := x
|
||
let mut y := y
|
||
if x > 0 then
|
||
let y' := x + 1
|
||
x := y'
|
||
else
|
||
y := y + 1
|
||
return x + y
|
||
|
||
theorem ex3 (y : Nat) : h 0 y = 0 + (y + 1) :=
|
||
rfl
|
||
|
||
theorem ex4 (y : Nat) : h 1 y = (1 + 1) + y :=
|
||
rfl
|
||
|
||
def sumOdd (xs : List Nat) (threshold : Nat) : Nat := Id.run <| do
|
||
let mut sum := 0
|
||
for x in xs do
|
||
if x % 2 == 1 then
|
||
sum := sum + x
|
||
if sum > threshold then
|
||
break
|
||
unless x % 2 == 1 do
|
||
continue
|
||
dbg_trace ">> x: {x}"
|
||
return sum
|
||
|
||
#eval sumOdd [1, 2, 3, 4, 5, 6, 7, 9, 11, 101] 10
|
||
|
||
theorem ex5 : sumOdd [1, 2, 3, 4, 5, 6, 7, 9, 11, 101] 10 = 16 :=
|
||
rfl
|
||
|
||
-- We need `Id.run` because we still have `Monad Option`
|
||
def find? (xs : List Nat) (p : Nat → Bool) : Option Nat := Id.run do
|
||
let mut result := none
|
||
for x in xs do
|
||
if p x then
|
||
result := x
|
||
break
|
||
return result
|
||
|
||
def sumDiff (ps : List (Nat × Nat)) : Nat := Id.run do
|
||
let mut sum := 0
|
||
for (x, y) in ps do
|
||
sum := sum + x - y
|
||
return sum
|
||
|
||
theorem ex7 : sumDiff [(2, 1), (10, 5)] = 6 :=
|
||
rfl
|
||
|
||
def f1 (x : Nat) : IO Unit := do
|
||
let rec loop : Nat → IO Unit
|
||
| 0 => pure ()
|
||
| x+1 => do IO.println x; loop x
|
||
loop x
|
||
|
||
#eval f1 10
|
||
|
||
partial def f2 (x : Nat) : IO Unit := do
|
||
let rec
|
||
isEven : Nat → Bool
|
||
| 0 => true
|
||
| x+1 => isOdd x,
|
||
isOdd : Nat → Bool
|
||
| 0 => false
|
||
| x+1 => isEven x
|
||
IO.println ("isOdd(" ++ toString x ++ "): " ++ toString (isOdd x))
|
||
|
||
#eval f2 11
|
||
#eval f2 10
|
||
|
||
def split (xs : List Nat) : List Nat × List Nat := Id.run do
|
||
let mut evens := []
|
||
let mut odds := []
|
||
for x in xs.reverse do
|
||
if x % 2 == 0 then
|
||
evens := x :: evens
|
||
else
|
||
odds := x :: odds
|
||
return (evens, odds)
|
||
|
||
theorem ex8 : split [1, 2, 3, 4] = ([2, 4], [1, 3]) :=
|
||
rfl
|
||
|
||
def f3 (x : Nat) : IO Bool := do
|
||
let y ← cond (x == 0) (do IO.println "hello"; pure true) (pure false);
|
||
pure !y
|
||
|
||
def f4 (x y : Nat) : Nat × Nat := Id.run <| do
|
||
let mut (x, y) := (x, y)
|
||
match x with
|
||
| 0 => y := y + 1
|
||
| _ => x := x + y
|
||
return (x, y)
|
||
|
||
#eval f4 0 10
|
||
#eval f4 5 10
|
||
|
||
theorem ex9 (y : Nat) : f4 0 y = (0, y+1) :=
|
||
rfl
|
||
|
||
theorem ex10 (x y : Nat) : f4 (x+1) y = ((x+1)+y, y) :=
|
||
rfl
|
||
|
||
def f5 (x y : Nat) : Nat × Nat := Id.run <| do
|
||
let mut (x, y) := (x, y)
|
||
match x with
|
||
| 0 => y := y + 1
|
||
| z+1 => dbg_trace "z: {z}"; x := x + y
|
||
return (x, y)
|
||
|
||
#eval f5 5 6
|
||
|
||
theorem ex11 (x y : Nat) : f5 (x+1) y = ((x+1)+y, y) :=
|
||
rfl
|
||
|
||
def f6 (x : Nat) : Nat := Id.run <| do
|
||
let mut x := x
|
||
if x > 10 then
|
||
return 0
|
||
x := x + 1
|
||
return x
|
||
|
||
theorem ex12 : f6 11 = 0 :=
|
||
rfl
|
||
|
||
theorem ex13 : f6 5 = 6 :=
|
||
rfl
|
||
|
||
def findOdd (xs : List Nat) : Nat := Id.run <| do
|
||
for x in xs do
|
||
if x % 2 == 1 then
|
||
return x
|
||
return 0
|
||
|
||
theorem ex14 : findOdd [2, 4, 5, 8, 7] = 5 :=
|
||
rfl
|
||
|
||
theorem ex15 : findOdd [2, 4, 8, 10] = 0 :=
|
||
rfl
|
||
|
||
def f7 (ref : IO.Ref (Option (Nat × Nat))) : IO Nat := do
|
||
let some (x, y) ← ref.get | pure 100
|
||
IO.println (toString x ++ ", " ++ toString y)
|
||
return x+y
|
||
|
||
def f7Test : IO Unit := do
|
||
unless (← f7 (← IO.mkRef (some (10, 20)))) == 30 do throw $ IO.userError "unexpected"
|
||
unless (← f7 (← IO.mkRef none)) == 100 do throw $ IO.userError "unexpected"
|
||
|
||
#eval f7Test
|
||
|
||
def f8 (x : Nat) : IO Nat := do
|
||
let y ←
|
||
if x == 0 then
|
||
IO.println "x is zero"
|
||
return 100 -- returns from the `do`-block
|
||
else
|
||
pure (x + 1)
|
||
IO.println ("y: " ++ toString y)
|
||
return y
|
||
|
||
def f8Test : IO Unit := do
|
||
unless (← f8 0) == 100 do throw $ IO.userError "unexpected"
|
||
unless (← f8 1) == 2 do throw $ IO.userError "unexpected"
|
||
|
||
#eval f8Test
|