Tim*_*son 9 haskell generic-programming
我正在编写处理来自Language.Exts.Annotated.Syntax的值的代码,其中定义了各种类型的镜像Haskell模块的结构:
data Module l = ...
data Decl l = ...
data Exp t = ...
-- etc
Run Code Online (Sandbox Code Playgroud)
我希望能够编写处理这些数据结构并对它们执行各种转换的函数.因为没有一种常见的数据类型,所以我无法编写一个可以完成所有操作的函数.
到目前为止,我已经编写了一个Tree包装这些类型的类型,以便我的转换函数可以执行Tree l -> Tree l:
data Tree l = ModuleT (Module l)
| DeclT (Decl l)
| ExpT (Exp l)
-- etc copy & paste
Run Code Online (Sandbox Code Playgroud)
但是我现在发现自己编写了很多代码,需要Module包含它ModuleT,包装它,调用函数,然后再将结果重新打包Module.我有:
class AnnotatedTree ast where
tree :: ast l -> Tree l
untree :: Tree l -> ast l
instance AnnotatedTree Module where
tree = ModuleT
untree (ModuleT x) = x
untree _ = error "expected ModuleT"
-- etc ad nauseam
Run Code Online (Sandbox Code Playgroud)
两个问题:
所有这些类型似乎都是Typeable和Data的实例.您可以将类型Tree定义为Typeable和Data的实例,然后使用一个可用的泛型库(SYB,uniplate,...)轻松遍历Tree.
我个人最喜欢的是uniplate.例如,从Tree收集所有GuardedAlt就像下面这样简单:
import Data.Uniplate.PlateData
...
allGuardedAlts :: Tree l -> [l]
allGuardedAlts t = [ l | GuardedAlt l _ _ <- universeBi t]
Run Code Online (Sandbox Code Playgroud)
你可以看看我的包graphtype我做了类似的事情.
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |