我想创建一个函数,它接受一些 Dec 类型的声明(我从 [d| ... |] 获得)并修改它们。修改将取决于以前的声明,因此我希望能够将它们存储在隐藏在 State monad 中的映射中 - 主要是我创建记录和类实例,并向它们添加以前记录中的字段。 (这样我想模仿 OOP,但这可能与我的问题无关)。我想在处理(并更改)所有声明后将计算结果拼接到代码中。
我尝试以各种可能的方式用 Q 组合 StatT,但我无法正确完成。
编辑
我的想法是创建收集类声明的函数(我知道 Haskell 不是面向对象的语言,我读了一些关于如何在 Haskell 中编码 OOP 的论文,并且我尝试使用 Template 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 中运行计算的问题。
最佳答案
Template Haskell 的一个问题是它的 API 不像大多数其他 Haskell 库那样完善。 Q
monad 充满了问题:它具体化、它呈现、它管理本地名称的状态。但交错问题域从来都不是一个好主意,因为事实证明,人类一次只能思考一件事(换句话说,我们是“单核”)。这意味着将问题混合在一起是不可扩展的。这就是为什么很难推理 Q
已经,并且您想在其之上添加另一个问题:您的状态。坏主意。
与任何其他问题一样,您应该通过关注点分离来解决这个问题。也就是说,您应该从主要问题域中提取较小的问题域,并单独处理每个问题域。关于 Template Haskell,有几个明显的领域:现有 AST 的具体化、它们的分析和新 AST 的呈现。对于这些域之间的通信,您可能还需要一些“通用语言”数据模型。有点想起什么,不是吗?是的,这就是 MVC。
提取的域有某些属性,您可以利用这些属性来获得好处:您只需保留在 Q
中即可。 monad for reification,渲染和分析可以在纯净的环境中完成,为您提供它的所有好处。您可以使用 unsafePerformIO . runQ
安全地净化准引号.
对于现实生活中的例子,我可以向您推荐我的一些项目,我在其中应用了这种方法:
关于haskell - StateT 与来自模板 haskell 的 Q monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23975681/