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
组合在一起,但我不推荐这样做。