模板Haskell:是否有函数(或特殊语法)解析String并返回Q Exp? [英] Template Haskell: Is there a function (or special syntax) that parses a String and returns Q Exp?

查看:103
本文介绍了模板Haskell:是否有函数(或特殊语法)解析String并返回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 to Q 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 was Language.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 to cabal 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 provides

parsePat :: String -> Either String Pat
parseExp :: String -> Either String Exp
parseType :: String -> Either String Type
parseDecs :: String -> Either String [Dec]

where Pat, Exp, Type, and Dec are the same as from Language.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 the Parser. It has functions to parse String into preliminary ASTs (whose data declarations are in HsSyn) 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 in Language.Haskell.TH.Syntax)?

Looking inside HsSyn, its obvious that the AST isn't quite the same as the one in Language.Haskell.TH.Syntax. Open up both HsExpr and Exp and side by side you'll see that the latter is filled with types like PostTc id <some-other-type> and PostRn 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 the Language.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 has HsSplice 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 what Haskell-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆