Haskell 提升抽象数据类型

Haskell 提升抽象数据类型,haskell,template-haskell,Haskell,Template Haskell,假设有一个方便的库来解析东西。它导出一个函数parseThing,以及一些类型和帮助程序: module Text.Thing.Parser ( Thing () , parseThing , ParseError -- ... ) where -- ... data Thing = {- implementation -} parseThing :: String -> Either ParseError Thing parseThing = {-

假设有一个方便的库来解析东西。它导出一个函数
parseThing
,以及一些类型和帮助程序:

module Text.Thing.Parser
   ( Thing ()
   , parseThing
   , ParseError

   -- ...

   ) where

-- ...

data Thing = {- implementation -}

parseThing :: String -> Either ParseError Thing
parseThing = {- implementation -}  
我决定编写一个包装器库,它可以在编译时进行解析

{-# LANGUAGE TemplateHaskell #-}
module Text.Thing.Parser.TH where

import Text.Thing.Parser

import Language.Haskell.TH
import Language.Haskell.TH.Quote

thingExpr :: String -> Q Exp
thingExpr src = do
  case parseThing src of
    Left err    -> fail $ show err
    Right thing -> [| thing |]

thing :: QuasiQuoter
thing = QuasiQuoter { quoteExp  = thingExpr
                    , quoteDec  = undefined
                    , quotePat  = undefined
                    , quoteType = undefined
                    }
编译失败,没有实例(Lift Thing)错误,但我无法添加实例声明,因为
Thing
是我无权访问的抽象数据类型:它在别处定义,并且没有导出构造函数。由于我是模板Haskell的新手,所以除了提升一个局部变量(如果有的话)之外,我无法想出一个解决方案


那么如何定义
thingExpr
?谢谢。

只有当你有一个函数
fromThing::Thing->T
toThing::T->Thing
时才可能,其中
T
是一个
Lift
实例的类型。请注意,
parseThing
满足后者,因此如果
Thing
有一个show实例,您可以这样做。在任何情况下,您都可以将其编写为
lift t t=[| toThing$([| fromThing t |]]|]
或者,您可以直接编写
thingExpr=[|任一(error“”)id(parseThing s)
。@user2407038,
thingExpr s=[|任一(error“”)id(parsethings)
与调用
任一(error“”)id基本相同(解析对象)
在运行时,我错了吗?你是对的。解析仍将在运行时完成。如果你有一些其他函数满足
fromThing
/
toThing
的要求,那么你可以在编译时进行解析,但“编组”将必须在运行时完成。可能有一些讨厌的黑客可以与
unsecfectorce
组合在一起,但我不推荐这样做。