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

Jef*_*own 2 macros haskell introspection template-haskell

我有一些变数ab.我想Data.Map.fromList [("a",a),("b",b)]通过输入类似的东西来快速创建地图magic [a,b].我想在GHCI中这样做,而不是在模块中.

我花了一些时间学习模板Haskell,但我仍然无法判断它是否可能.是吗?

Car*_*arl 5

好的,这是一个非常快速和脏的实现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)) |]
Run Code Online (Sandbox Code Playgroud)

这是在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)]’
Run Code Online (Sandbox Code Playgroud)

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

这段代码很快而且很脏,但是快乐的路径是正确的.错误情况导致代码无法拼接,但不一定导致最友好的错误消息.总而言之......这是一个起点.

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

{-# 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)) |]
Run Code Online (Sandbox Code Playgroud)