Jef*_*own 2 macros haskell introspection template-haskell
我有一些变数a
和b
.我想Data.Map.fromList [("a",a),("b",b)]
通过输入类似的东西来快速创建地图magic [a,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)) |]
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)