假设有一些数据类型来表达 lambda 和组合项:
data Lam α = Var α -- v
| Abs α (Lam α) -- λv . e1
| App (Lam α) (Lam α) -- e1 e2
deriving (Eq, Show)
infixl 0 :@
data SKI α = V α -- x
| SKI α :@ SKI α -- e1 e2
| I -- I
| K -- K
| S -- S
deriving (Eq, Show)
还有一个函数可以获取 lambda 项的自由变量列表:
fv ∷ Eq α ⇒ Lam α → [α]
fv (Var v) = [v]
fv (Abs x e) = filter (/= x) $ fv e
fv (App e1 e2) = fv e1 ++ fv e2
将 lambda 项转换为组合项抽象消除规则可能很有用:
convert ∷ Eq α ⇒ Lam α → SKI α
1) T[x] => x
convert (Var x) = V x
2) T[(E₁ E₂)] => (T[E₁] T[E₂])
convert (App e1 e2) = (convert e1) :@ (convert e2)
3) T[λx.E] => (KT[E]) (如果 x 在 E 中不自由出现)
convert (Abs x e) | x `notElem` fv e = K :@ (convert e)
4) T[λx.x] => 我
convert (Abs x (Var y)) = if x == y then I else K :@ V y
5) T[λx.λy.E] => T[λx.T[λy.E]] (如果 x 在 E 中自由出现)
convert (Abs x (Abs y e)) | x `elem` fv e = convert (Abs x (convert (Abs y e)))
6) T[λx.(E₁ E₂)] => (ST[λx.E₁] T[λx.E₂])
convert (Abs x (App y z)) = S :@ (convert (Abs x y)) :@ (convert (Abs x z))
convert _ = error ":["
这个定义是无效的,因为5)
:
Couldn't match expected type `Lam α' with actual type `SKI α'
In the return type of a call of `convert'
In the second argument of `Abs', namely `(convert (Abs y e))'
In the first argument of `convert', namely
`(Abs x (convert (Abs y e)))'
所以,我现在拥有的是:
> convert $ Abs "x" $ Abs "y" $ App (Var "y") (Var "x")
*** Exception: :[
我想要的是(希望我计算正确):
> convert $ Abs "x" $ Abs "y" $ App (Var "y") (Var "x")
S :@ (S (KS) (S (KK) I)) (S (KK) I)
问题:
如果 lambda 项和组合项具有不同类型的表达式,那么如何5)
正确表述呢?