2004年11月07日
2004年11月07日
LambdaTermつづき
import Char(isSpace,isAlpha)
--Def: Lambda Term
data Variable = Var Char deriving(Eq)
data LambdaTerm = VT Variable
| FuncAbs Variable LambdaTerm
| FuncApp LambdaTerm LambdaTerm
deriving(Eq)
--show and read
instance Show Variable where
showsPrec _ (Var c) = (c:)
instance Show LambdaTerm where
showsPrec _ (VT var) = showsPrec 0 var
showsPrec _ (FuncAbs var term) = ("(/"++) . showsPrec 0 var . ('.':) . showsPrec 0 term . (')':)
showsPrec _ (FuncApp t0 t1) = ('(':) . showsPrec 0 t0 . showsPrec 0 t1 . (')':)
instance Read Variable where
readsPrec _ [] = []
readsPrec _ s = if isAlpha c then [(Var c,l)] else []
where (c:l) = dropWhile isSpace s
instance Read LambdaTerm where
readsPrec _ s = [(VT var,q) | (var,q) <- reads s]
++
[(FuncAbs var term,q) |
("(",l00) <- lex s,
("/",l01) <- lex l00,
(var,l1) <- reads l01,
(".",l2) <- lex l1,
(term,l3) <- reads l2,
(")",q) <- lex l3]
++
[(FuncApp t0 t1,q) |
("(",l0) <- lex s,
(t0,l1) <- reads l0,
(t1,l2) <- reads l1,
(")",q) <- lex l2]
--for only reading omit format of lambda-term
data LambdaTermOmit = VTOmit Variable
| FuncAbsOmit [Variable] [LambdaTermOmit]
| FuncAppOmit [LambdaTermOmit]
instance Read LambdaTermOmit where
readsPrec _ s = [(VTOmit x,q) | (x,q) <- reads s]
++
[(FuncAbsOmit (x:xs) (t:ts),q) |
("(",l0) <- lex s,
("/",l1) <- lex l0,
(x,l2) <- reads l1, --needs at least one parameter
(xs,l3) <- readlv l2, --terminated by "."
(t,l4) <- reads l3,
(ts,q) <- readlt l4] --terminated by ")"
++
[(FuncAppOmit (x:y:xs),q) |
("(",l0) <- lex s,
(x,l1) <- reads l0,
(y,l2) <- reads l1,
(xs,q) <- readlt l2] --terminated by ")"
++
[(lto,q) |
("(",l0) <- lex s,
(lto,l1) <- reads l0,
(")",q) <- lex l1]
where readlv s = [([],q) | (".",q)<- lex s] ++
[(x:xs,q) | (x,l) <- reads s,
(xs,q) <- readlv l]
readlt :: String -> [([LambdaTermOmit],String)]
readlt s = [([],q) | (")",q)<- lex s] ++
[(x:xs,q) | (x,l) <- reads s,
(xs,q) <- readlt l]
validLTomit :: LambdaTermOmit -> Bool
validLTomit (VTOmit var) = True
validLTomit (FuncAbsOmit vs l) = (and (map validLTomit l)) && unique vs
where unique (x:xs) = (not(x `elem` xs)) && (unique xs)
unique [] = True
validLTomit (FuncAppOmit p) = (and (map validLTomit p))
canonicalize :: LambdaTermOmit -> LambdaTerm
canonicalize (VTOmit var) = (VT var)
canonicalize (FuncAbsOmit (x:xs) ts) = (FuncAbs (x) (canonicalize(FuncAbsOmit xs ts)))
canonicalize (FuncAbsOmit [] ts) = (canonicalize (FuncAppOmit ts))
--left associate
canonicalize (FuncAppOmit [x,y]) = FuncApp (canonicalize x) (canonicalize y)
canonicalize (FuncAppOmit []) = error "never come"
canonicalize (FuncAppOmit l) = canonicalize(la l)
where la (x:y:xs) = la ((FuncAppOmit [x,y]):xs)
la [x] = x
readLambdaTerm :: String -> LambdaTerm
readLambdaTerm s = if validLTomit o then canonicalize o else error "invalid FunctionalAbstruction"
where o :: LambdaTermOmit
o = read ("("++s++")")
--Def: FV (free variable), closed term
fv :: LambdaTerm -> [Variable]
fv (VT var) = [var]
fv (FuncApp t0 t1) = (fv t0)++(fv t1)
fv (FuncAbs x t) = filter (x/=) (fv t)
isClosedTerm t = (fv t)==[]
--Def: Leftmost Reduction
isBetaNormalForm :: LambdaTerm -> Bool
isBetaNormalForm (VT var) = True
isBetaNormalForm (FuncAbs x t) = False
isBetaNormalForm (FuncApp p q) = (isBetaNormalForm p) && (isBetaNormalForm q)
--betaRedexReduction :: FuncApp (FuncAbs Variable LambdaTerm) LambdaTerm -> LambdaTerm
betaRedexReduction :: LambdaTerm -> LambdaTerm
betaRedexReduction (FuncApp (FuncAbs x t) s) = replaceLT t x s
betaRedexReduction o = error "bad argument"
replaceLT :: LambdaTerm -> Variable -> LambdaTerm -> LambdaTerm
replaceLT s@(VT var) from to = if var==from then to else s
replaceLT (FuncAbs x t) from to = (FuncAbs x (if x==from then t else (replaceLT t from to))) --guards
replaceLT (FuncApp p q) from to = (FuncApp (replaceLT p from to) (replaceLT q from to))
leftmostReduction :: LambdaTerm -> LambdaTerm
leftmostReduction (VT var) = (VT var)
leftmostReduction (FuncAbs x t) = error "dont have beta-nf"
leftmostReduction b@(FuncApp (FuncAbs x t) s) = betaRedexReduction b
leftmostReduction a@(FuncApp p q) | haslambda p = FuncApp (leftmostReduction p) q
| haslambda q = FuncApp p (leftmostReduction q)
| otherwise = a
where haslambda (VT var)=False
haslambda (FuncAbs x t)=False
haslambda (FuncApp (FuncAbs x t) q)=True
haslambda (FuncApp p q) = (haslambda p) || (haslambda q)
associateFreeVariable :: LambdaTerm -> [(Variable,LambdaTerm)] -> LambdaTerm
associateFreeVariable t [] = t
associateFreeVariable t (y:ys)= associateFreeVariable (FuncApp (FuncAbs v t) l) ys
where (v,l) = y
--main
readLT = readLambdaTerm
lmr = leftmostReduction
afv = associateFreeVariable
lmrloop l = if isBetaNormalForm l then l else lmrloop (lmr l)
lmrloopprint l = do
putStrLn(show(l))
if isBetaNormalForm l
then return()
else lmrloopprint (lmr l)
main :: IO()
main = do
lmrloopprint skkx
-- lmrloopprint ym
where k = readLT "(/xy.x)"
s = readLT "(/xyz.xz(yz))"
skk = readLT "skk"
skkx = FuncApp (afv skk [(Var 's',s),(Var 'k',k)]) (VT (Var 'x'))
ym = readLT "(/y.(/x.y(xx))(/x.y(xx)))m"
らぶHaskell。これC++で書く気になれないなぁ。
lexのあやしい構文を使う時、haskell-modeが邪魔だ。
一応本に忠実。\lambdaのかわりに"/"、省略記法対応。 mainではSKKxを最左変換(leftmost reduction)してxがでてくる。
*Main> main (((/k.((/s.((sk)k))(/x.(/y.(/z.((xz)(yz)))))))(/x.(/y.x)))x) (((/s.((s(/x.(/y.x)))(/x.(/y.x))))(/x.(/y.(/z.((xz)(yz))))))x) ((((/x.(/y.(/z.((xz)(yz)))))(/x.(/y.x)))(/x.(/y.x)))x) (((/y.(/z.(((/x.(/y.x))z)(yz))))(/x.(/y.x)))x) ((/z.(((/x.(/y.x))z)((/x.(/y.x))z)))x) (((/x.(/y.x))x)((/x.(/y.x))x)) ((/y.x)((/x.(/y.x))x)) x
haskellの本それなりにまとまってるんだけど、標準ライブラリについてはあまり書いてない。 Prelude他のソースはかなり参考になる。
そういえば最近の読書
最近やっとboost本を買った。どうせリファレンスならもっとでかくてもよかったと思ったが、リファレンスではないのか。
Python入門(O'Reilly)つうのも入手した。でも1/3ほど読んでpythonへの熱はさめた。
学校を出よう(6)が熱い。ハルヒのほうが売れてるみたいだけど。