您如何将 lambda 术语转换为交互网络?
How do you translate from lambda terms to interaction nets?
在 this paper 上,作者建议在 lambda 术语之间进行翻译:
data Term = Zero | Succ Term | App Term Term | Lam Term
和交互网:
data Net = -- if I understood correctly
Apply Net Net Net
| Abstract Net Net Net
| Delete Net Net Int
| Duplicate Net Net Net Int
| Erase Net
很遗憾我无法理解他的编译算法。似乎缺少实际的算法,我不知道他对第三页上的图像意味着什么。我试图通过查看已发布的源代码来理解它,但作者使用他自己的图形重写 DSL 来定义它,所以我必须先学习它。翻译究竟是如何实现为普通 Haskell 功能的?
我有一个 implementation of interaction net reduction in Haskell,它使用 STRef
s 以可变方式表示网络图结构:
data NodeType = NRot
| NLam
| NApp
| NDup Int
| NEra
deriving (Show)
type NodeID = Int
type Port s = STRef s (Node s, PortNum)
data Node s = Node
{ nodeType :: !NodeType
, nodeID :: !NodeID
, nodePort0, nodePort1, nodePort2 :: !(Port s)
}
lambda 术语的转换是在 separate module. It is not the nicest code I've ever written, because it's a straight transliteration of a Javascript implementation 中实现的,我并没有真正花时间去了解 JS 版本在做什么:
encodeLam :: Lam -> IntNet s (Node s)
encodeLam lam = do
nextTag <- do
ref <- lift $ newSTRef 0
return $ lift $ do
modifySTRef ref succ
readSTRef ref
let go scope up (Lam body) = do
del <- mkNode NEra
lam <- mkNode NLam
linkHalf lam P0 up
link (lam, P1) (del, P0)
link (del, P1) (del, P2)
bod <- go (lam:scope) (lam, P2) body
linkHalf lam P2 bod
return (lam, P0)
go scope up (App f e) = do
app <- mkNode NApp
linkHalf app P2 up
linkHalf app P0 =<< go scope (app, P0) f
linkHalf app P1 =<< go scope (app, P1) e
return (app, P2)
go scope up (Var v) = do
let lam = scope !! v
(target, targetPort) <- readPort lam P1
case nodeType target of
NEra -> do
linkHalf lam P1 up
return (lam, P1)
_ -> do
dup <- mkNode . NDup =<< nextTag
linkHalf dup P0 (lam, P1)
linkHalf dup P1 up
link (dup, P2) =<< readPort lam P1
linkHalf lam P1 (dup, P0)
return (dup, P1)
root <- asks root
enc <- go [] (root, P0) lam
linkHalf root P0 enc
return root
它也实现了反向转换:
decodeLam :: Node s -> IntNet s Lam
decodeLam root = do
(setDepth, getDepth) <- do
ref <- lift $ newSTRef mempty
let set node depth = lift $ modifySTRef ref $
IntMap.insertWith (\ _new old -> old) (nodeID node) depth
get node = lift $ (! nodeID node) <$> readSTRef ref
return (set, get)
let go depth exit (node, port) = do
setDepth node depth
case nodeType node of
NDup _ -> do
let (port', exit') = case port of
P0 -> (head exit, tail exit)
_ -> (P0, port:exit)
go depth exit' =<< readPort node port'
NLam -> case port of
P1 -> do
depth' <- getDepth node
return $ Var (depth - depth' - 1)
_ -> Lam <$> (go (succ depth) exit =<< readPort node P2)
NApp -> do
f <- go depth exit =<< readPort node P0
e <- go depth exit =<< readPort node P1
return $ App f e
go 0 [] =<< readPort root P0
在 this paper 上,作者建议在 lambda 术语之间进行翻译:
data Term = Zero | Succ Term | App Term Term | Lam Term
和交互网:
data Net = -- if I understood correctly
Apply Net Net Net
| Abstract Net Net Net
| Delete Net Net Int
| Duplicate Net Net Net Int
| Erase Net
很遗憾我无法理解他的编译算法。似乎缺少实际的算法,我不知道他对第三页上的图像意味着什么。我试图通过查看已发布的源代码来理解它,但作者使用他自己的图形重写 DSL 来定义它,所以我必须先学习它。翻译究竟是如何实现为普通 Haskell 功能的?
我有一个 implementation of interaction net reduction in Haskell,它使用 STRef
s 以可变方式表示网络图结构:
data NodeType = NRot
| NLam
| NApp
| NDup Int
| NEra
deriving (Show)
type NodeID = Int
type Port s = STRef s (Node s, PortNum)
data Node s = Node
{ nodeType :: !NodeType
, nodeID :: !NodeID
, nodePort0, nodePort1, nodePort2 :: !(Port s)
}
lambda 术语的转换是在 separate module. It is not the nicest code I've ever written, because it's a straight transliteration of a Javascript implementation 中实现的,我并没有真正花时间去了解 JS 版本在做什么:
encodeLam :: Lam -> IntNet s (Node s)
encodeLam lam = do
nextTag <- do
ref <- lift $ newSTRef 0
return $ lift $ do
modifySTRef ref succ
readSTRef ref
let go scope up (Lam body) = do
del <- mkNode NEra
lam <- mkNode NLam
linkHalf lam P0 up
link (lam, P1) (del, P0)
link (del, P1) (del, P2)
bod <- go (lam:scope) (lam, P2) body
linkHalf lam P2 bod
return (lam, P0)
go scope up (App f e) = do
app <- mkNode NApp
linkHalf app P2 up
linkHalf app P0 =<< go scope (app, P0) f
linkHalf app P1 =<< go scope (app, P1) e
return (app, P2)
go scope up (Var v) = do
let lam = scope !! v
(target, targetPort) <- readPort lam P1
case nodeType target of
NEra -> do
linkHalf lam P1 up
return (lam, P1)
_ -> do
dup <- mkNode . NDup =<< nextTag
linkHalf dup P0 (lam, P1)
linkHalf dup P1 up
link (dup, P2) =<< readPort lam P1
linkHalf lam P1 (dup, P0)
return (dup, P1)
root <- asks root
enc <- go [] (root, P0) lam
linkHalf root P0 enc
return root
它也实现了反向转换:
decodeLam :: Node s -> IntNet s Lam
decodeLam root = do
(setDepth, getDepth) <- do
ref <- lift $ newSTRef mempty
let set node depth = lift $ modifySTRef ref $
IntMap.insertWith (\ _new old -> old) (nodeID node) depth
get node = lift $ (! nodeID node) <$> readSTRef ref
return (set, get)
let go depth exit (node, port) = do
setDepth node depth
case nodeType node of
NDup _ -> do
let (port', exit') = case port of
P0 -> (head exit, tail exit)
_ -> (P0, port:exit)
go depth exit' =<< readPort node port'
NLam -> case port of
P1 -> do
depth' <- getDepth node
return $ Var (depth - depth' - 1)
_ -> Lam <$> (go (succ depth) exit =<< readPort node P2)
NApp -> do
f <- go depth exit =<< readPort node P0
e <- go depth exit =<< readPort node P1
return $ App f e
go 0 [] =<< readPort root P0