そう。
#eval は見た目こそ「式を評価している」ように見えるけど、実際には普通の項の簡約(β簡約やδ簡約)とは別物だ。
例えば
#eval 2 + 3
は 5 を表示する。
しかしこれは
#check 2 + 3
のようにカーネル内で式を扱っているのとは違い、Lean のコンパイラとランタイムを使って実際にコードを実行している。
特に
#eval IO.rand
が動くことからもわかる。
もし #eval が単なる関数評価なら、
IO.rand : IO Nat
は Nat に評価できない。
実際には
- IO.rand という IO Nat の値を作る
- Lean のランタイムがその IO アクションを実行する
- 得られた Nat を表示する
という処理をしている。
⸻
逆に、カーネルが行う「普通の評価」は
#reduce (fun x => x + 1) 3
みたいなもの。
#reduce IO.rand
をやっても乱数は出ない。
なぜなら #reduce は外界と相互作用しない純粋な簡約しか行わないから。
⸻
極端に言うと、
#eval e
は
Leanプログラムをコンパイル
↓
実行
↓
結果を表示
に近い。
一方
#reduce e
は
式そのものを数学的に簡約
に近い。
だから
Lean では #eval で即実行できるけど、普通の関数評価とは違うことをしているんやね
その理解で正しい。#eval は「項の評価」というより「Lean の実行系にその項を走らせている」操作だ。Haskell で言えば GHCi が main を実行しているのに近い。
そう。
#eval は見た目こそ「式を評価している」ように見えるけど、実際には普通の項の簡約(β簡約やδ簡約)とは別物だ。
例えば
#eval 2 + 3
は 5 を表示する。
しかしこれは
#check 2 + 3
のようにカーネル内で式を扱っているのとは違い、Lean のコンパイラとランタイムを使って実際にコードを実行している。
特に
#eval IO.rand
が動くことからもわかる。
もし #eval が単なる関数評価なら、
IO.rand : IO Nat
は Nat に評価できない。
実際には
という処理をしている。
⸻
逆に、カーネルが行う「普通の評価」は
#reduce (fun x => x + 1) 3
みたいなもの。
#reduce IO.rand
をやっても乱数は出ない。
なぜなら #reduce は外界と相互作用しない純粋な簡約しか行わないから。
⸻
極端に言うと、
#eval e
は
Leanプログラムをコンパイル
↓
実行
↓
結果を表示
に近い。
一方
#reduce e
は
式そのものを数学的に簡約
に近い。
だから
Lean では #eval で即実行できるけど、普通の関数評価とは違うことをしているんやね
その理解で正しい。#eval は「項の評価」というより「Lean の実行系にその項を走らせている」操作だ。Haskell で言えば GHCi が main を実行しているのに近い。