模板Haskell:是否有函数(或特殊语法)解析String并返回Q Exp? [英] Template Haskell: Is there a function (or special syntax) that parses a String and returns Q Exp?
问题描述
我想学习一些模板Haskell和Quasi Quotation,并且我正在寻找一个函数,它需要一个 String
并将其解析为 Q Exp
,因此类型为:
字符串 - > Q Exp
尝试搜索hoogle,但是我看到的结果与将字符串提升到 Q Exp
,而且我发现的最接近的是 Language.Haskell.TH.dyn
,它完全符合我的要求,但仅限于一个变量。
是否有其他选项?例如。一个特殊的语法?我只是在熟悉 [||]
和 $()
的过程中,所以也许有
一个我如何设想的例子:
runQ(parse(1+))== InfixE(Just(LitE(IntegerL 1)))(VarE GHC.Num。+)Nothing
pre>
另外,我知道这个
runQ [| (1+)|] == InfixE(Just(LitE(IntegerL 1)))(VarE GHC.Num。+)Nothing
但是这不适用于变量字符串,因为 - 理解 - 字符串里面的字符串被视为字面值。
runQ [| (1+)|] == LitE(StringL(1+))
Edit(2015-07-25):我已经开始使用
haskell-src-meta
,并且目前看起来效果很好。然而,对于cabal install
(我的机器上大约需要10分钟)需要相当多的时间。这是一个耻辱,我的包实际上很小,我想如果安装可以很快。任何人都知道具有较小依赖性的解决方案?
解决方案大家已经说过了
haskell-src-meta
提供parsePat :: String - >或者String Pat
parseExp :: String - >字符串Exp
parseType :: String - >字符串类型
parseDecs :: String - > String [Dec]
其中
Pat
,Exp
,类型
和Dec
与从Language.Haskell。 TH.Syntax
。
'GHC公开它自己的解析器?
它的确如此。使用
ghci -package ghc
(ghc
默认为隐藏包)启动GHCi,您可以导入Parser
。它具有将String
解析为初步AST(其数据声明位于HsSyn
)的模式,表达式,类型和
$ b
好的,那为什么不存在一个使用这个解析器的库,并将它的输出转换成
template-haskell
(Language.Haskell.TH.Syntax
)?
寻找内部
HsSyn
,很明显AST与Language.Haskell.TH.Syntax
。打开HsExpr
和Exp
并排,您会看到后者填充了PostTc id< some-other-type>
和PostRn id< some-other-type>
。当AST从解析器传递到重命名器到类型检查器时,这些零件都被缓慢填充。例如,我们甚至不知道操作符的固定性,直到我们进行类型检查!
为了实现我们想要的功能,我们需要运行的不仅仅是解析器(至少是更名器和类型检查器,也许更多)。想象一下:每次你想要解析一个像
1 + 2
这样的小表达式时,你仍然需要键入检查一堆导入。即便如此,转换回Language.Haskell.TH.Syntax
不会在公园散步:GHC具有各种各样的特性,例如它自己特有的全球存储名称和标识符的方式。 / p>
<> H but but but but GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH GH
这是最酷的部分!与
Exp
不同,HsExpr
有HsSplice
用于表示接头。查看前两个构造函数的类型:
HsTypedSplice :: id - > LHsExpr id - > HsSplice ID。 - 像[|| 1 + 2 ||]
HsUntypedSplice :: id - > LHsExpr id - > HsSplice id - 诸如[| 1 + 2 |]
注意,它们不存储
String
,他们已经存储了一个AST!拼接与AST的其余部分同时进行解析。就像AST的其余部分一样,拼接将传递给重命名器,类型检查器等,以填补缺失的信息。
$ b $因此,使用GHC的解析器是根本不可能的。
可能不是。但从GHC的其余部分中解脱出来可能相当困难。如果使用GHC的解析器,我们还必须运行类型检查器和重命名器,使用独立解析器(如
haskell-src-exts
)可能更优雅,更简单。 (这就是Haskell-src-meta
所依赖的),它能够一次完成所有任务(例如,修复程序是您必须提供的一项功能提前到这个解析器)。I am trying to learn a bit of Template Haskell and Quasi Quotation, and I am looking for a function that takes a
String
and parses it toQ Exp
, so the type is:String -> Q Exp
Tried searching hoogle, but the results I saw had to do with lifting String literals to
Q Exp
, and the closest I found wasLanguage.Haskell.TH.dyn
which does quite what I want, but only for a single variable.Are there other options? E.g. a special syntax? I'm just in the process of familiarizing myself with
[||]
and$()
, so maybe there is something for this purpose too?An example of how I imagine it would work:
runQ (parse "(1+)") == InfixE (Just (LitE (IntegerL 1))) (VarE GHC.Num.+) Nothing
Also, I am aware of this
runQ [| (1+) |] == InfixE (Just (LitE (IntegerL 1))) (VarE GHC.Num.+) Nothing
but this wont work with variable strings because -- understandably -- the string inside is taken as a literal.
runQ [| "(1+)" |] == LitE (StringL "(1+)")
Edit (2015-07-25): I've started using
haskell-src-meta
, and it seems to work well so far. However it does take quite a bit of time tocabal install
(about 10 minutes on my machine). Which is a shame, my package is actually rather small, and I would like if install could be quick. Anyone knows of a solution that has smaller dependencies?解决方案As everyone has already said
haskell-src-meta
providesparsePat :: String -> Either String Pat parseExp :: String -> Either String Exp parseType :: String -> Either String Type parseDecs :: String -> Either String [Dec]
where
Pat
,Exp
,Type
, andDec
are the same as fromLanguage.Haskell.TH.Syntax
.
Why doesn't GHC expose its own parser?
It does. Fire up GHCi with
ghci -package ghc
(ghc
is a hidden package by default) and you can import theParser
. It has functions to parseString
into preliminary ASTs (whose data declarations are inHsSyn
) for patterns, expressions, types, and declarations.OK, then why does there not exist a library that uses this parser and converts its output to be the AST from
template-haskell
(the one inLanguage.Haskell.TH.Syntax
)?Looking inside
HsSyn
, its obvious that the AST isn't quite the same as the one inLanguage.Haskell.TH.Syntax
. Open up bothHsExpr
andExp
and side by side you'll see that the latter is filled with types likePostTc id <some-other-type>
andPostRn id <some-other-type>
. As the AST is passed from the parser to the renamer to the type checker, these bits and pieces are all slowly filled in. For example, we don't even know the fixities of operators until we get to type-checking!In order to make the functions we want, we would need to run much more than just the parser (at least the renamer and type checker too, maybe more). Imagine that: every time you want to parse even a small expression like
"1 + 2"
you'll still have to type check a bunch of imports. Even then, converting back to theLanguage.Haskell.TH.Syntax
wouldn't be a walk in the park: GHC has a variety of peculiarities like its own special global way of storing names and identifiers.Hmmm... but what does GHC do with quasi-quotes?
That's the cool part! Unlike
Exp
,HsExpr
hasHsSplice
for representing splices. Look at the types for the first two constructors:HsTypedSplice :: id -> LHsExpr id -> HsSplice id. -- things like [|| 1 + 2 ||] HsUntypedSplice :: id -> LHsExpr id -> HsSplice id -- things like [| 1 + 2 |]
Notice that they aren't storing
String
, they are storing an AST already! Splices get parsed at the same time as the rest of the AST. And just like the rest of the AST, the splices will get passed along to the renamer, type checker, etc. where missing information will be filled in.So is it fundamentally impossible to use GHC's parser
Probably not. But extricating it from the rest of GHC may be quite difficult. If to use GHC's parser we have to also run the type-checker and the renamer, it may be more elegant and simple to just use a standalone parser like
haskell-src-exts
(which is whatHaskell-src-meta
depends on) that is able to do everything in one pass (fixities, for example, are one of the things you have to give ahead of time to this parser).这篇关于模板Haskell:是否有函数(或特殊语法)解析String并返回Q Exp?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!