我刚刚开始使用模板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)
这可行,但是如果我保证它返回该类型的函数,那就更好了,那就是让它返回
Q (TExp (b -> a))
而不是Q Exp
。到目前为止,我所看到的有关生成类型表达式的所有内容都使用拼接和准引用。有没有一种方法可以从模板haskell构造函数生成它?
最佳答案
哦,嘿,TExp :: Exp -> TExp a
中有一个 Language.Haskell.TH.Syntax
constructor,所以我可以使用它:
surj f = fmap (TExp . LamCaseE . concat) ...
不利的一面是
TExp
指定的类型仅在拼接时才被检查(有点像C++模板),但这是TH固有的。