Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating TExp using Template Haskell

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?

like image 964
rampion Avatar asked Mar 29 '20 14:03

rampion


1 Answers

Oh hey, there's a TExp :: Exp -> TExp a constructor in Language.Haskell.TH.Syntax, so I can just use that:

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

There's the downside that the type specified by TExp only gets checked at splice time (kind of like a C++ template), but that's inherent to TH.

like image 169
rampion Avatar answered Sep 29 '22 21:09

rampion