如何获取 Haskell 代码字符串(连同值)

Posted

技术标签:

【中文标题】如何获取 Haskell 代码字符串(连同值)【英文标题】:How can I get the string of Haskell code (along with the value) 【发布时间】:2021-10-18 01:05:17 【问题描述】:

我想获取任意 Haskell 代码的字符串和值。例如:

f (1+1) -> (2,"1+1")

我想这样做的原因是因为我正在编写一种编程语言,并且我想提供一个选项来解释代码(用于快速运行,即脚本)或将其编译为 Haskell 代码(用于高效运行时)。因此,对于每个内置函数,我只想提供一次实现。那就是我不想说

plusop = ((+),"(+)")

我有一些想法,包括阅读原始的 haskell 源代码或生成编译器的单独脚本,但如果这个问题是可能的,这些似乎没有那么优雅。

看起来 QuasiQuotation 可以使这成为可能,但如果我使用它,我不知道如何获取表达式的 Haskell 值(我只能获取字符串)。

有可能吗?怎么办?

【问题讨论】:

您可以使用Hint Haskell interpreter 是的,但我认为这可能会非常低效,因为它会解释所有代码,但是这样操作中的大部分代码仍然被编译。此外,编写解释器比编写编译器更容易(这本质上就是编写编译器——尽管目前这是我所做的,所以可能还不错)。 【参考方案1】:

我不知道你到底想做什么,但这里有一个使用 Template Haskell 做与你的例子类似的事情的例子:

-- TH.hs
-# LANGUAGE TemplateHaskell #-
module TH where

import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Ppr

showAndRun :: Q Exp -> Q Exp
showAndRun m = do
  x <- m
  let s = pprint x
  [| ($m, s) |]
-- Main.hs
-# LANGUAGE TemplateHaskell #-
import TH

main :: IO ()
main = print $(showAndRun [| 1 + 1 |])
$ runhaskell Main.hs
(2,"1 GHC.Num.+ 1")

我不知道如何在没有限定 GHC.Num 前缀的情况下漂亮地打印表达式。您可以尝试复制Language.Haskell.TH.Ppr 的实现并在必要的地方进行更改。或者最简单的可能只是一个后处理步骤,您可以删除以大写字母开头并以. 结尾的每个单词。

【讨论】:

谢谢,这就是我想做的! GHC 编号添加在那里很好,因为那仍然是无需修改即可编译的haskell代码

以上是关于如何获取 Haskell 代码字符串(连同值)的主要内容,如果未能解决你的问题,请参考以下文章

Haskell:如何将 IO 输入字符串解析为 Float(或 Int 或其他)?

如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?

如何在 Haskell 的“let”表达式中用“type”定义一个值?

如何在 Haskell 中解析 IO 字符串?

在 Haskell 中生成下一个字典字符串

如何在 haskell 中打印列表?