open Lean def f : IO Nat := pure 0 def g (x : Nat) : IO Nat := pure (x + 1) def g1 {α : Type} (x : α) : IO (α × α) := pure (x, x) def g2 (p : Nat × Nat) : Nat := p.1 -- set_option trace.Elab.definition true def h (x : Nat) : StateT Nat IO Nat := do let s ← get let a ← f -- liftM inserted here let b ← g1 1 -- liftM inserted here let x := g2 b IO.println b pure (s+a) def myPrint {α} [ToString α] (a : α) : IO Unit := IO.println s!">> {a}" def h₂ (x : Nat) : StateT Nat IO Nat := do let a ← h 1; -- liftM inserted here IO.println x let b ← g1 a -- liftM inserted here if a > 100 then throw $ IO.userError "Error" myPrint b.1 -- liftM inserted here pure (a + 1) def h₃ (x : Nat) : StateT Nat IO Nat := do let m1 := do -- Type inferred from application below discard <| g x -- liftM inserted here IO.println 1 let m2 (y : Nat) := do -- Type inferred from application below discard <| h (x+y) -- liftM inserted here myPrint y -- liftM inserted here let a ← h 1 -- liftM inserted here IO.println x let b ← g1 a; -- liftM inserted here if a > 100 then throw $ IO.userError "Error" myPrint b.1 -- liftM inserted here m1 m2 a pure 1 def tst0 : IO Unit := do let a ← f let x := a + 1 IO.println "hello" IO.println x def tst1 : IO Unit := do let a ← f; let x := a + 1; IO.println "hello"; IO.println x; def tst2 : IO Unit := do let x := ← g $ (←f) + (←f); IO.println "hello"; IO.println x def tst3 : IO Unit := do if (← g 1) > 0 then IO.println "gt" else let x ← f; let y ← g x; IO.println y def pred (x : Nat) : IO Bool := do return (← g x) > 0 def tst4 (x : Nat) : IO Unit := do if ← pred x then IO.println "is true" else IO.println "is false" def pred2 (x : Nat) : IO Bool := do return x > 0 def tst5 (x : Nat) : IO (Option Nat) := if x > 10 then pure x else pure none def tst6 (x : Nat) : StateT Nat IO (Option Nat) := if x > 10 then g x else pure none syntax:max (name := doHash) "#" : term partial def expandHash : Syntax → StateT Bool MacroM Syntax | Syntax.node k args => if k == `doHash then do set true; `(←MonadState.get) else do let args ← args.mapM expandHash; pure $ Syntax.node k args; | stx => pure stx @[macro Lean.Parser.Term.do] def expandDo : Macro := fun stx => do let (stx, expanded) ← expandHash stx false; if expanded then pure stx else Macro.throwUnsupported def tst7 : StateT (Nat × Nat) IO Unit := do if #.1 == 0 then IO.println "first field is zero" else IO.println "first field is not zero" #check tst7 #eval tst7.run (0, 2) def f1 (x : Nat) : StateT Nat IO Nat := do IO.println "hello" let mut z := x let mut y := x modify (· + 10) if x > 0 then y := 3*y z := z + (← get) + (← get) if x < (← get) then IO.println s!">> {y}" return y else IO.println s!"++ {z}" return y+z def f1Test : IO Unit := do unless (← f1 30 |>.run' 0) == 140 do throw $ IO.userError $ "error" unless (← f1 5 |>.run' 0) == 15 do throw $ IO.userError $ "error" #eval f1Test