Skip to content

Instantly share code, notes, and snippets.

@jacobstanley
Last active August 12, 2019 22:01
Show Gist options
  • Save jacobstanley/a988c042840dd3004a4d8e9b07f4d8ca to your computer and use it in GitHub Desktop.
Save jacobstanley/a988c042840dd3004a4d8e9b07f4d8ca to your computer and use it in GitHub Desktop.
Quasi-quoter which captures source
-- Quoter unfortunately need to be in another file due to GHC staging restrictions
import Quoter
foo :: ParsedExpr
foo =
[expr| Var "salads" |]
-- foo =
ParsedExpr {parsedSource = " Var \"salads\" ", parsedExpr = Var "salads"}
bar :: ParsedExpr
bar =
[expr| Lam "f" (Lam "g" (Lam "x" (App (Var "g") (App (Var "f") (Var "x"))))) |]
-- bar =
ParsedExpr
{ parsedSource =
" Lam \"f\" (Lam \"g\" (Lam \"x\" (App (Var \"g\") (App (Var \"f\") (Var \"x\"))))) "
, parsedExpr =
Lam "f" (Lam "g" (Lam "x" (App (Var "g") (App (Var "f") (Var "x")))))
}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Quoter where
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
data Expr =
Var String
| Lam String Expr
| App Expr Expr
deriving (Read, Show, Data, Lift)
data ParsedExpr =
ParsedExpr {
parsedSource :: String
, parsedExpr :: Expr
} deriving (Show, Data, Lift)
expr :: QuasiQuoter
expr =
qq $ \source -> do
x <- maybe (Left "no parse") Right (readMaybe source)
pure $
ParsedExpr {
parsedSource = source
, parsedExpr = x
}
qq :: Data a => (String -> Either String a) -> QuasiQuoter
qq f =
QuasiQuoter {
quoteExp = either fail liftData . f
, quotePat = const (fail "soz no pats")
, quoteType = const (fail "soz no types")
, quoteDec = const (fail "soz no decs")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment