Генерация TExp с использованием шаблона Haskell - PullRequest
7 голосов
/ 29 марта 2020

Я только начинаю с шаблона 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 конструкторов?

1 Ответ

1 голос
/ 30 марта 2020

О, эй, есть TExp :: Exp -> TExp a конструктор в Language.Haskell.TH.Syntax, поэтому я могу просто использовать это:

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

Есть обратная сторона, что тип, указанный в TExp проверяется только во время соединения (вроде шаблона C ++), но это присуще TH.

...