Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
来自模板haskell的带有Q monad的StateT_Haskell_Monad Transformers_Template Haskell_State Monad - Fatal编程技术网

来自模板haskell的带有Q monad的StateT

来自模板haskell的带有Q monad的StateT,haskell,monad-transformers,template-haskell,state-monad,Haskell,Monad Transformers,Template Haskell,State Monad,我想创建一个函数,它接受一些Dec类型的声明(我从[d |…|]中得到)并修改它们。修改将取决于以前的声明,所以我希望能够将它们存储在状态monad中隐藏的map中-主要是我创建记录和类实例,并从以前的记录向它们添加字段。(这样我想模仿OOP,但这可能与我的问题无关)。我希望在处理(并更改)所有声明后将计算结果拼接到代码中 我试着用Q的各种可能的方法来创作StatT,但我做不好 编辑 我的想法是创建收集类声明的函数(我知道Haskell不是面向对象的语言,我读了一些关于如何在Haskell中编码

我想创建一个函数,它接受一些Dec类型的声明(我从[d |…|]中得到)并修改它们。修改将取决于以前的声明,所以我希望能够将它们存储在状态monad中隐藏的map中-主要是我创建记录和类实例,并从以前的记录向它们添加字段。(这样我想模仿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
data Env = Env {classes :: Map.Map Name Dec }
type QS a = (StateT Env Q) a

这是(例如C++代码)< /P>的编码 我想用模板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编码工作原理,但我希望能够自动生成它,而不是手工编写

我在declare函数中与DecsQ进行交互时遇到问题,可能我希望它以如下形式存在:

declare [d| class A a where 
                attr1 :: a -> Int
                attr2 :: a -> Int |]
declareInherit [d| class B b where
                      attr3 :: b -> Int |] ''A
data Env = Env {classes :: Map.Map Name Dec }
type QS a = (StateT Env Q) a

我还遇到了如何在QS中运行计算的问题

模板Haskell的一个问题是,它的API并不像大多数其他Haskell库那样精巧。
Q
monad有很多问题:它具体化、呈现、管理本地名称的状态。但将问题域交错起来从来都不是一个好主意,因为已经证明人类一次只能思考一件事(换句话说,我们是“单核心”)。这意味着将问题混合在一起是不可伸缩的。这就是为什么很难对
Q
进行推理的原因,你想在上面再加上一个问题:你的状态。坏主意

与任何其他问题一样,您应该以分离关注点的方式处理此问题。也就是说,你应该从你的主要问题域中提取较小的问题域,并单独处理它们中的每一个。关于模板Haskell,有几个明显的领域:现有AST的具体化、新AST的分析和呈现。对于这些域之间的通信,您可能还需要一些“通用语言”数据模型。有点让人想起了什么,不是吗?是的,是MVC

提取的域具有某些属性,您可以利用这些属性为自己带来好处:您只需保留在
Q
单子中进行具体化,渲染和分析可以在纯环境中完成,从而为您带来所有好处。您可以使用
unsafePerformIO安全地净化准引号。runQ

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


模板Haskell的一个问题是,它的API没有像大多数其他Haskell库那样精巧。
Q
monad有很多问题:它具体化、呈现、管理本地名称的状态。但将问题域交错起来从来都不是一个好主意,因为已经证明人类一次只能思考一件事(换句话说,我们是“单核心”)。这意味着将问题混合在一起是不可伸缩的。这就是为什么很难对
Q
进行推理的原因,你想在上面再加上一个问题:你的状态。坏主意

与任何其他问题一样,您应该以分离关注点的方式处理此问题。也就是说,你应该从你的主要问题域中提取较小的问题域,并单独处理它们中的每一个。关于模板Haskell,有几个明显的领域:现有AST的具体化、新AST的分析和呈现。对于这些域之间的通信,您可能还需要一些“通用语言”数据模型。有点让人想起了什么,不是吗?是的,是MVC

提取的域具有某些属性,您可以利用这些属性为自己带来好处:您只需保留在
Q
单子中进行具体化,渲染和分析可以在纯环境中完成,从而为您带来所有好处。您可以使用
unsafePerformIO安全地净化准引号。runQ

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


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

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

然后执行类似于
runIO(readIORef env)的操作:Q env

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

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

然后做一些事情,比如
runIO(readIORef-env)::Q env

我知道这是一个令人沮丧的答案,但如果你的目的是实现一些有成效的事情,你真的不想在Haskell中模仿OOP。在Haskell中可以有效地使用OOP的某些方面,但您所做的不是其中之一。您应该在问题中包含代码。现在还不清楚你希望实现什么
Q
是一个monad,但您不必使用它的monad属性-您只需使用
QDec
QExp
QType
类型即可。您需要更具体一些。你到底遇到了什么问题
StateT
Q
的组合与任何其他monad一样好。我知道这是一个令人沮丧的非答案,但如果你的目的是完成一些有成效的事情,你真的不想在Haskell中模仿OOP。在Haskell中可以有效地使用OOP的某些方面,但您所做的不是其中之一。您应该在问题中包含代码。它仍然是联合国