I'm just getting started with template haskell.
I've written a function that takes a function a -> [b]
and generates an expression for a function 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)
This works, but it'd be nice if I could promise that it returns a function of that type, that is have it return a Q (TExp (b -> a))
rather than a Q Exp
.
Everything I've seen thus far about generating typed expressions uses splices and quasiquotes. Is there a way to generate it from template haskell constructors?