StateT与Q monad来自模板haskell

时间:2014-06-01 00:24:10

标签: haskell monad-transformers template-haskell state-monad

我想创建一个函数,它接受Dec类型的声明(我从[d | ... |]得到)并修改它们。修改将取决于之前的声明,所以我希望能够将它们存储在状态monad中隐藏的地图中 - 主要是我创建记录和类实例并从之前的记录中添加它们的字段。 (这种方式我想模仿OOP,但这可能与我的问题无关)。在处理(和更改)所有声明之后,我想将计算结果拼接到代码中。

我尝试用Q尽可能地编写StatT,但我无法做到。

修改

我的想法是创建收集类声明的函数(我知道Haskell不是面向对象的语言,我读了一些关于如何在Haskell中编码OOP的文章,我尝试用模板Haskell作为小任务实现它)。

所以我希望能够写出这样的东西:

declare [d| class A a where 
                attr1 :: a -> Int
                attr2 :: a -> Int |]
declareInherit [d| class B b where
                      attr3 :: b -> Int |] ''A

这是(例如c ++代码)

的编码
struct A{
    int attr1;
    int attr2;
}
struct B : A {
    int attr3;
}

我想用模板haskell生成两条记录:

data A_data = A_data { attr1' :: Int, attr2' :: Int}
data B_data = B_data { attr1'' :: Int, attr2'' :: Int, attr3'' :: Int}

和类的实例:

instance A A_data where
    attr1 = attr1'
    attr2 = attr2'

instance A B_data where
    attr1 = attr1''
    attr2 = attr2''

instance B B_data where
    attr3 = attr3''

这就是我的OO编码的工作方式,但我希望能够自动生成它,而不是手工编写。

我在声明函数中遇到与DecsQ交互的问题,可能我希望它存在于这样的事情中:

data Env = Env {classes :: Map.Map Name Dec }
type QS a = (StateT Env Q) a

我也有问题如何在QS中运行计算。

2 个答案:

答案 0 :(得分:4)

Template Haskell的一个问题是它的API不如大多数其他Haskell库那样精致。 Q monad超载了问题:它通过渲染,渲染,管理本地名称的状态。但是,交错问题领域永远不是一个好主意,因为它已经被证明人类一次只能想到一件事(换句话说,我们是"单核心" )。这意味着将问题混合在一起是不可扩展的。这就是为什么很难对Q进行推理的原因,并且你想在它上面添加另一个问题:你的状态。不好的主意。

除了任何其他问题,你应该通过分离关注来解决这个问题。也就是说,您应该从主要问题域中提取较小的问题域并单独使用它们。关于模板Haskell,有几个明显的领域:现有AST的具体化,它们的分析和新AST的呈现。对于这些域之间的通信,您可能还需要一些"通用语言"数据模型。有点想起一些事情,不是吗?是的,它的MVC。

提取的域有某些属性,然后您可以利用这些属性:您只需要保留在Q monad中进行具体化,渲染和分析可以在纯环境中完成,授予你有它的所有好处。您可以使用unsafePerformIO . runQ安全地净化准引号。

对于现实生活中的例子,我可以向您介绍我的一些项目,其中我采用了这种方法:

答案 1 :(得分:0)

至少在一个文件中,您可以将状态从一个DecsQ拼接传递到文件中的下一个拼接,方法是将其存储在:

{-# NOINLINE env #-}
env :: IORef Env
env = unsafePerformIO (newIORef (Env mempty))

然后执行runIO (readIORef env) :: Q Env

之类的操作
相关问题