首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法阻止Data.Generics.Alloy.GenInstances扫描Data.Text.Internal?

有没有办法阻止Data.Generics.Alloy.GenInstances扫描Data.Text.Internal?
EN

Stack Overflow用户
提问于 2018-06-11 03:20:59
回答 1查看 47关注 0票数 5

我需要对AST进行转换;下面是AST的一部分:

代码语言:javascript
复制
data Expr
  = BinExpr { beOp    :: BinaryOp
            , beLeft  :: Expr
            , beRight :: Expr }
  | Name Text
  | IntegerLit Integer
  | StringLit Text
  deriving (Data, Typeable)

这是一个相当复杂的AST,所以涉及很多类型。

我使用合金生成泛型转换,特别是:

代码语言:javascript
复制
autoGen :: IO ()
autoGen = do
  createDirectoryIfMissing True baseDir
  writeInstancesTo inst doc imports targetFile
  where
    inst = allInstances GenWithoutOverlapped
    doc = [genInstance (undefined :: Doc)]
    imports = header ++ instanceImports

现在,这在使用String时很好,但我正在尝试迁移到Data.Text。当代码生成运行时,它将读取Data.Text的内部内容,如下所示:

代码语言:javascript
复制
instance (Alloy ([(GHC.Types.Char)]) (f :- ops) BaseOp) =>
     Alloy ((Data.Text.Internal.Text)) BaseOp (f :- ops) where
  transform _ ops (Data.Text.Internal.pack a0)
      =  Data.Text.Internal.pack
     (transform ops BaseOp (a0))

我相信pack与GHC内部元素有关联,所以这不是一个有效的模式匹配,而且不管怎么说,让代码与Data.Text的内部元素混在一起很容易破坏不变量。(编辑:看起来有一个instance Data Text where gfoldl f z txt = z packf(unpack txt)声明,但无论如何,我不需要/希望遍历文本值。)

有没有办法强迫合金把一种类型当作原子呢?我希望避免使用newtype来包装文本,因为所有处理as的代码都需要处理它,这与使用泛型来避免样板的目的不同。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-11 11:24:02

也许可以试试这个技巧:我们将Expr类型参数化,以便在用合金派生实例时覆盖用于TextData实例。

代码语言:javascript
复制
data Expr_ text
  = BinExpr { beOp    :: BinaryOp
            , beLeft  :: Expr_ text
            , beRight :: Expr_ text }
  | Name text
  ...
  | StringLit text

代码库的其余部分可以使用这个同义词,希望不会过多地解决类型推断问题。

代码语言:javascript
复制
type Expr = Expr_ Text

但是对于Data-generic操作,我们在Text周围使用一个newtype包装器,并使其行为像一个髓构造函数,希望合金不需要gunfold的结果(或者您可以使用模式同义词使其表现为字符串)。

代码语言:javascript
复制
newtype DataText = DataText Text

instance Data DataText where
  gunfold _ f _ = f undefined
  ...

然后,autoGen将专门处理DummyText的所有内容。

使用Data.Coerce.coerce可以方便地在Expr_ DataTextExpr上的函数之间进行转换。

代码语言:javascript
复制
coerce :: Expr_ DataText -> Expr
coerce :: Expr -> Expr_ DataText
coerce :: (Expr_ DataText -> Expr_ DataText) -> Expr -> Expr

这可能用于根据从您派生的实例为Expr编写合金类型类的实例。它有点样板,但希望它能够被包含和隐藏,而不会影响代码的其余部分。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50790121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档