[英]how to reify a list of data using Data.Reify?
I tried to read the paper ( http://www.ittc.ku.edu/csdl/fpg/sites/default/files/Gill-09-TypeSafeReification.pdf ) and managed to reify my symbolic expression type, but I can't figure out how to reify a list of them. 我试着阅读这篇论文( http://www.ittc.ku.edu/csdl/fpg/sites/default/files/Gill-09-TypeSafeReification.pdf )并设法重新启用我的符号表达式类型,但我可以'弄清楚如何重新列出它们的清单。 Here's the simplified code: 这是简化的代码:
{-# OPTIONS_GHC -Wall #-}
{-# Language TypeOperators #-}
{-# Language TypeFamilies #-}
{-# Language FlexibleInstances #-}
import Control.Applicative
import Data.Reify
-- symbolic expression type
data Expr a = EConst a
| EBin (Expr a) (Expr a)
deriving Show
-- corresponding node type
data GraphExpr a b = GConst a
| GBin b b
deriving Show
instance MuRef (Expr a) where
type DeRef (Expr a) = GraphExpr a
mapDeRef _ (EConst c) = pure (GConst c)
mapDeRef f (EBin u v) = GBin <$> f u <*> f v
-- this works as expected
main :: IO ()
main = reifyGraph (EBin x (EBin x y)) >>= print
where
x = EConst "x"
y = EConst "y"
-- (output: "let [(1,GBin 2 3),(3,GBin 2 4),(4,GConst "y"),(2,GConst "x")] in 1")
-- but what if I want to reify a list of Exprs?
data ExprList a = ExprList [Expr a]
data GraphList a b = GraphList [GraphExpr a b]
instance MuRef (ExprList a) where
type DeRef (ExprList a) = GraphList a
-- mapDeRef f (ExprList xs) = ???????
I had the exact same problem, and I found a solution using data-reify. 我有完全相同的问题,我找到了一个使用data-reify的解决方案。
The things you have to realise to arrive at a solution is that: 1. Even though the EDSL doesnt have lists, the graph type could contain them 2. It is possible to reify different types of data to the same result type. 为了得到解决方案,你必须意识到的事情是:1。即使EDSL没有列表,图表类型也可以包含它们2.可以将不同类型的数据统一到相同的结果类型。
So we start by adding list constructors to our result type: 所以我们首先在结果类型中添加列表构造函数:
data GraphExpr a b = GConst a
| GBin b b
| Cons b b
| Nil
deriving Show
Then we need a second instance of MuRef, that reifies lists of Expr a to GraphExpr. 然后我们需要MuRef的第二个实例,它将Expr a的列表统一到GraphExpr。
instance MuRef [Expr a] where
type DeRef [Expr a] = GraphExpr a
mapDeRef _ [] = pure Nil
mapDeRef f (x:xs) = Cons <$> f x <*> f xs
Now with this in place, if we try to reify a list expression 现在有了这个,如果我们尝试重新列出一个列表表达式
reified = reifyGraph [EBin x (EBin x y), Ebin y (EBin x y)]
where x = EConst "x"
y = EConst "y"
We'll get the result 我们会得到结果
let [(1,Cons 2 6),(6,Cons 7 9),(9,Nil),(7,GBin 5 8),(8,GBin 3 5),(2,GBin 3 4),(4,GBin 3 5),(5,GConst "y"),(3,GConst "x")] in 1
To extract the list of reified node-ids from this graph we can define a little function to walk the Conses and to extract the node-ids from them into a list. 要从此图中提取已知的节点ID列表,我们可以定义一个小函数来遍历Conses并将节点ID从它们提取到列表中。
walkConses :: Graph (GraphExpr t) -> [Unique]
walkConses (Graph xs root) = go (lookup root xs)
where
go (Just (Cons n1 n2)) = n1 : go (lookup n2 xs)
go (Just Nil) = []
(If the graphs are huge, it might be a good idea to convert them to an IntMap before starting the walk) (如果图形很大,那么在开始漫步之前将它们转换为IntMap可能是个好主意)
This looks like a partial function, but since we know that the root of the DAG will always be a Cons-node (since we reify a list), and since we know that all node-ids are in xs this function will return a list of all node-ids in the result list. 这看起来像是一个部分函数,但是因为我们知道DAG的根将始终是Cons节点(因为我们重新列出了一个列表),并且因为我们知道所有node-id都在xs中,所以这个函数将返回一个列表结果列表中的所有node-id。
So if we run walkConses on our resulting graph we'll get the result: 因此,如果我们在结果图上运行walkConses,我们将得到结果:
[2, 7]
Hope this helps, I've been wrestling with this problem for a while too. 希望这会有所帮助,我也一直在努力解决这个问题。
You really can't do that with MuRef. 你真的不能用MuRef做到这一点。 GraphLists don't contain GraphLists. GraphLists不包含GraphLists。 You can reify each Expr in turn and write a one-off combinator to smash them into your GraphList though: 您可以依次重新启动每个Expr并编写一个一次性组合器,将它们粉碎到您的GraphList中:
Just use traverse reifyGraph over the ExprList contents. 只需在ExprList内容上使用遍历reifyGraph。
Also, both of the latter should probably be newtypes. 此外,后者都应该是新类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.