Skip to content

Instantly share code, notes, and snippets.

@youz
Last active December 14, 2018 04:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save youz/d22fa360541d7aa1ecbbabf3697ccc24 to your computer and use it in GitHub Desktop.
Save youz/d22fa360541d7aa1ecbbabf3697ccc24 to your computer and use it in GitHub Desktop.
SATySFiでラムダ計算
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@require: stdja
@require: list
@require: math
@require: option
% ref. http://www.kb.ecei.tohoku.ac.jp/~sumii/class/keisanki-software-kougaku-2005/lambda.pdf
type exp =
| Var of string * int
| Abs of exp * exp
| App of exp * exp
let vareq x y =
match (x, y) with
| (Var(s, i), Var(t, j)) -> string-same s t && i == j
| _ -> false
let-rec allvar
| ((Var _) as v) = [v]
| (Abs(x, e)) = x :: (allvar e)
| (App(x, y)) = List.append (allvar x) (allvar y)
let-rec find eq x l =
match l with
| [] -> None
| e :: r -> if eq x e then Some(e) else find eq x r
let dedup eq l =
List.fold-left (fun a e -> (
match find eq e a with
| None -> e :: a
| Some _ -> a
)) [] l
let-mutable sym-counter <- -1
let-mutable sym-used <- []
let-rec gensym () =
let () = sym-counter <- !sym-counter + 1 in
let c = string-unexplode [!sym-counter mod 26 + 97] in
let p = !sym-counter / 26 in
let v = Var(c, p) in
match find vareq v !sym-used with
| None -> v
| Some _ -> gensym ()
let-rec subst e2 x e1 =
match e1 with
| Var(_) -> if vareq x e1 then e2 else e1
| Abs(y, e) ->
let y2 = gensym () in
Abs(y2, subst e2 x (subst y2 y e))
| App(e, f) ->
App(subst e2 x e, subst e2 x f)
let-rec step e =
match e with
| Var(x) -> None
| Abs(x, e0) -> (
match step e0 with
| None -> None
| Some(e) -> Some(Abs(x, e))
)
| App(e1, e2) -> (
match e1 with
| Abs(x, e0) -> Some(subst e2 x e0)
| _ -> (
match step e1 with
| Some(e) -> Some(App(e, e2))
| None -> (
match step e2 with
| Some(e) -> Some(App(e1, e))
| None -> None
)))
let reduct-all e lim =
let-rec r e a i =
if i > lim then
List.reverse (e :: a)
else
match step e with
| None -> List.reverse (e :: a)
| Some(f) -> r f (e :: a) (i + 1)
in
r e [] 0
let-rec repeat-string
| s 0 = ` `
| s n = s ^ (repeat-string s (n - 1))
let-rec exp2math
| (Var(x, i)) =
let p = math-char MathOrd (repeat-string `′` i) in
${\mathit-token!(x)#p}
| (Abs(x, e)) =
let mx = exp2math x in
let me = exp2math e in
${\lambda #mx . #me}
| (App(x, y)) =
let mx = exp2math x in
let px = match x with
| Var _ -> mx
| App(_, Var _) -> mx
| _ -> ${\(#mx\)}
in
let my = exp2math y in
let py = match y with
| Var _ -> my
| _ -> ${\(#my\)}
in
math-concat px py
let-block ctx +lambdacalc lm lexp =
let () = sym-counter <- -1 in
let () = sym-used <- (dedup vareq (allvar lexp)) in
let (f::r) = reduct-all lexp 100 |> List.map exp2math in
let ml = [lm; ${= #f}] :: (List.map (fun m -> [${}; ${\to #m}]) r) in
read-block ctx '<+align(ml);>
let var s = Var(s, 0)
let abs v e = Abs(v, e)
let app e1 e2 = App(e1, e2)
let cnum n =
let f = var `f` in
let x = var `x` in
let-rec r
| 0 a = a
| i a = r (i - 1) (app f a)
in
abs f (abs x (r n x))
% pred = λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u)
let pred =
let f = var `f` in
let g = var `g` in
let h = var `h` in
let n = var `n` in
let u = var `u` in
let x = var `x` in
abs n (abs f (abs x (app (app (app n (abs g (abs h (app h (app g f))))) (abs u x)) (abs u u))))
in
document (|
title = {\SATySFi;でλ計算};
author = {youz};
show-title = false;
show-toc = false;
|) '<
+lambdacalc(${3^2})(app (cnum 2) (cnum 3));
+lambdacalc(${\text!({pred})\ 3})(app pred (cnum 3));
>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment