module Control.Applicative.QQ.Idiom (i) where
import Control.Applicative
import Language.Haskell.Meta (parseExp)
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax
i :: QuasiQuoter
i = QuasiQuoter { quoteExp = applicateQ }
applicateQ :: String -> ExpQ
applicateQ s = case either fail unwindE (parseExp s) of
x:y:xs -> foldl
(\e e' -> [|$e <*> $e'|])
[|$(return x) <$> $(return y)|]
(fmap return xs)
_ -> fail "applicateQ fails."
unwindE :: Exp -> [Exp]
unwindE = go []
where go acc (e `AppE` e') = go (e':acc) e
go acc e = e:acc