2

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

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

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

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

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

看起来 QuasiQuotation 可以使这成为可能,但是如果我使用它,我无法弄清楚如何获取表达式的 Haskell 值(我只能获取字符串)。

是否可以?如何做呢?

4

1 回答 1

4

我不确切知道您想做什么,但这里有一个使用 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并在必要的地方进行更改。或者最简单的可能只是一个后处理步骤,您可以删除以大写字母开头并以 . 结尾的每个单词.

于 2021-08-15T20:39:28.413 回答