Haskell 宏来创建一个从他们的名字到一些表达式的映射?

Haskell macro to create a Map from their names to some expressions?

我有一些变量 ab。我想通过键入类似 magic [a,b] 的内容来快速创建地图 Data.Map.fromList [("a",a),("b",b)]。我想在 GHCI 中实时执行此操作,而不是在模块内执行此操作。

为此我花了一些时间学习模板 Haskell,但我什至不知道它是否可行。是吗?

好的,这里是 magic 的一个非常快速和肮脏的实现:

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import qualified Data.Map as M

magic :: [String] -> ExpQ
magic xs = [| M.fromList $(listE (map toPair xs)) |]
  where
    toPair nameStr = do
        Just name <- lookupValueName nameStr
        [| (nameStr, $(varE name)) |]

这里是在 ghci 中使用它:

$ ghci -XTemplateHaskell thmagic.hs
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( thmagic.hs, interpreted )
Ok, one module loaded.
*Main> let x = 1 ; y = 2 ; z = "hello"
*Main> $(magic ["x", "y"])
fromList [("x",1),("y",2)]
*Main> $(magic ["x", "y", "z"])

<interactive>:3:3: error:
    • No instance for (Num [Char]) arising from a use of ‘x’
    • In the expression: x
      In the expression: ("x", x)
      In the first argument of ‘M.fromList’, namely
        ‘[("x", x), ("y", y), ("z", z)]’

注意在ghci中启用了模板haskell,$()拼接语法用于告诉它实际拼接生成的表达式。还要注意在没有的情况下的编译错误每个列表条目都具有相同的类型。

这段代码又快又脏,但快乐的道路是正确的。错误情况导致代码拼接失败,但不一定带有最友好的错误消息。总而言之...这是一个起点

编辑 - 具有最少输入键击的版本,如下面的评论所述:

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import qualified Data.Map as M

magic :: String -> ExpQ
magic names = [| M.fromList $(listE (map toPair (words names))) |]
  where
    toPair nameStr = do
        Just name <- lookupValueName nameStr
        [| (nameStr, $(varE name)) |]