在Haskell中转换AST

时间:2014-11-05 02:18:47

标签: parsing haskell abstract-syntax-tree

有许多Haskell教程将源解析为AST,AST重写,AST评估,但没有关于两个AST之间的映射。有没有"规范"在transformFoo2Bar中实施Haskell的方式?

type FooIdentifier = String
data Foo = Foo FooIdentifier [FooMethod] deriving (Show)
data FooMethod = FooMethod FooIdentifier [FooExpression] deriving (Show)
data FooExpression = FooAB FooIdentifier FooIdentifier | FooZ FooIdentifier deriving (Show)

type BarIdentifier = String
type BarLabel = String
data Bar = Bar BarIdentifier [BarExpression] deriving (Show)
data BarExpression = BarA BarIdentifier BarIdentifier 
                   | BarB BarIdentifier BarIdentifier | BarZ BarIdentifier deriving (Show)

--
-- transformFoo2Bar [Foo "foo" [FooMethod "foo1" [FooAB "a" "b", FooZ "z"], FooMethod "foo2" [FooZ "z"]]]
--         
-- to evaluate to 
--
-- [Bar "foo_foo1" [BarA "a" "b", BarB "a" "b", BarZ "z"], Bar "foo_foo2" [BarZ "z"]] 
--

transformFoo2Bar :: [Foo] -> [Bar]
transformFoo2Bar = undefined

与代码编译类似,但不是发出编译代码,而是将结果保存为AST。

也可以将这些映射中的一些重用作反向映射吗?

由于

1 个答案:

答案 0 :(得分:1)

非常不正常这样做的方法是将BarExpression的定义更改为

data BarExpression = BarB BarIdentifier | BarA BarIdentifier BarIdentifier deriving (Show)

这样它不仅在结构上类似于FooExpression,而且具有相同的运行时表示。

然后您可以使用Unsafe.Coerce.unsafeCoerce

fe1 = FooA "a"
fe2 = FooB "x" "y"

fm1= FooMethod "meth1" [fe1,fe2]

foo1 = Foo "foo" [fm1]

允许你这样做

ghci> unsafeCoerce foo1 :: Bar
Bar "foo" [BarProc "meth1" [BarB "a",BarA "x" "y"]]

<font size+=1000 color="red"><blink>

警告程序员:

</blink></font>

我不建议这样做,因为它会让你的永恒的灵魂处于危险之中,一看到它就会意外地突破,并以非常非常糟糕的方式(如果你不交换) BarExpression此示例开始导致段错误:-)但它适用于特定用例。

或者,您可以摆脱其中一种同构类型;你有什么理由不这样做吗?