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

Ben*_*Ben 5 haskell

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

data Expr
  = BinExpr { beOp    :: BinaryOp
            , beLeft  :: Expr
            , beRight :: Expr }
  | Name Text
  | IntegerLit Integer
  | StringLit Text
  deriving (Data, Typeable)
Run Code Online (Sandbox Code Playgroud)

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

我正在使用合金来生成通用转换,具体来说:

autoGen :: IO ()
autoGen = do
  createDirectoryIfMissing True baseDir
  writeInstancesTo inst doc imports targetFile
  where
    inst = allInstances GenWithoutOverlapped
    doc = [genInstance (undefined :: Doc)]
    imports = header ++ instanceImports
Run Code Online (Sandbox Code Playgroud)

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

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))
Run Code Online (Sandbox Code Playgroud)

我认为pack它与GHC内部结构相关联,因此不是有效的模式匹配,并且无论如何,使用Data.Text内部的代码都会破坏不变量.(编辑:看起来有一个instance Data Text where gfoldl f z txt = z packf (unpack txt)声明,但无论如何,我不需要/想要遍历文本值.)

有没有办法强迫Alloy将类型视为原子?我希望避免使用newtype来包装Text,因为所有使用AST的代码都需要处理它,这相当违背了使用泛型来避免样板的目的.

Li-*_*Xia 2

也许可以尝试这个技巧:我们参数化Expr类型以覆盖在使用合金派生实例时Data使用的实例。Text

data Expr_ text
  = BinExpr { beOp    :: BinaryOp
            , beLeft  :: Expr_ text
            , beRight :: Expr_ text }
  | Name text
  ...
  | StringLit text
Run Code Online (Sandbox Code Playgroud)

代码库的其余部分可以使用这个同义词,希望不会因为类型推断问题而破坏太多。

type Expr = Expr_ Text
Run Code Online (Sandbox Code Playgroud)

但对于Data泛型操作,我们使用newtype包装器Text并使其表现得像无效构造函数,希望合金不需要结果gunfold(或者也许您可以使用模式同义词使其表现得像字符串)。

newtype DataText = DataText Text

instance Data DataText where
  gunfold _ f _ = f undefined
  ...
Run Code Online (Sandbox Code Playgroud)

autoGen然后将专注于 的一切DummyText

用于在和Data.Coerce.coerce上的函数之间轻松转换。Expr_ DataTextExpr

coerce :: Expr_ DataText -> Expr
coerce :: Expr -> Expr_ DataText
coerce :: (Expr_ DataText -> Expr_ DataText) -> Expr -> Expr
Run Code Online (Sandbox Code Playgroud)

这可能用于Expr根据从您派生的实例来编写合金类型类的实例。这是一些样板文件,但希望它可以被包含和隐藏,而不影响其余的代码。