parse-0.1.0.0: src/Parse/Internal/Instances.hs
module Parse.Internal.Instances where
import Control.Monad
import Data.List.Split (splitOn)
import Language.Haskell.TH
-- Dear future self,
-- You're looking at this file because the parseTupleInstance function finally broke.
-- It's not fixable. You have to rewrite it.
-- Sincerely, past self.
class ParseTuple a where
parseTuple :: String -> String -> Either String a
parseTupleInstance :: Int -> Q Dec
parseTupleInstance n = do
unless (n > 0) $
fail $ "Non-positive size: " ++ show n
doParse <- [|parseParts (splitOn "{}" format) str|]
invalidLengthL <- [p|Right result|]
invalidLengthR <- [|Left $ "Parsed " ++ show (length result) ++ " values, expected " ++
show n ++ "."|]
parseErrorL <- [p|Left x|]
parseErrorR <- [|Left x|]
let vars = [mkName ('t' : show n) | n <- [1..n]]
tupleSignature = foldl (\acc var -> AppT acc (ConT $ mkName "String")) (TupleT n) vars
-- foldl (\acc var -> AppT acc (VarT var)) (TupleT n) vars
parseList = ListP $ map VarP vars
parse = TupE $ map (Just . -- AppE (VarE $ mkName "read")
VarE) vars
-- context = map (AppT (ConT $ mkName "Read") . VarT) vars
iDecl = InstanceD Nothing [] -- context
(AppT (ConT $ mkName "ParseTuple") tupleSignature) [parseDecl]
parseDecl =
-- `parseTuple` function
FunD (mkName "parseTuple")
-- only has one clause
[Clause
-- Arguments: format and str
[VarP $ mkName "format", VarP $ mkName "str"]
-- Body
(NormalB
(CaseE doParse
[ Match (ConP (mkName "Right") [parseList])
(NormalB (AppE (ConE $ mkName "Right") parse)) []
, Match invalidLengthL (NormalB invalidLengthR) []
, Match parseErrorL (NormalB parseErrorR) [] ]))
-- Where
[]]
pure iDecl
parseTupleInstances :: [Int] -> Q [Dec]
parseTupleInstances = mapM parseTupleInstance