首页 > 解决方案 > 使用模板 Haskell 生成 TExp

问题描述

我刚刚开始使用模板haskell。

我编写了一个函数,它接受一个函数a -> [b]并为函数生成一个表达式b -> a

{-# OPTIONS_GHC -Wall -Wextra -Werror #-}
module Surjection where
import Language.Haskell.TH
import Data.Traversable

surj :: (Show a, Show b, Bounded a, Enum a) => (a -> [b]) -> Q Exp -- Q (TExp (b -> a))
surj f = fmap (LamCaseE . concat) .                             -- \case 
  forM [minBound .. maxBound] $ \a -> do
    Just aName <- lookupValueName (show a)
    forM (f a) $ \b -> do
      Just bName <- lookupValueName (show b)
      return $ Match (ConP bName []) (NormalB (ConE aName)) [] --     $(bName) -> $(aName)

这行得通,但如果我能保证它返回该类型的函数,那就太好了,也就是说让它返回 aQ (TExp (b -> a))而不是 a Q Exp

到目前为止,我所看到的关于生成类型化表达式的所有内容都使用拼接和准引号。有没有办法从模板haskell构造函数生成它?

标签: haskelltemplate-haskell

解决方案


哦,嘿,有一个TExp :: Exp -> TExp a构造函数Language.Haskell.TH.Syntax所以我可以使用它:

surj f = fmap (TExp . LamCaseE . concat) ...

有一个缺点是只在拼接时检查指定的类型TExp(有点像 C++ 模板),但这是 TH 所固有的。


推荐阅读