{-# OPTIONS -fglasgow-exts #-} module GRead2 () where {- For the discussion in the 2nd boilerplate paper, we favour some simplified generic read, which is checked to compile. For the full/real story see Data.Generics.Text. -} import Data.Generics gread :: Data a => String -> Maybe a gread input = runDec input readM -- The decoder monad newtype DecM a = D (String -> Maybe (String, a)) instance Monad DecM where return a = D (\s -> Just (s,a)) (D m) >>= k = D (\s -> case m s of Nothing -> Nothing Just (s1,a) -> let D n = k a in n s1) runDec :: String -> DecM a -> Maybe a runDec input (D m) = do (_,x) <- m input return x parseConstr :: DataType -> DecM Constr parseConstr ty = D (\s -> match s (dataTypeConstrs ty)) where match :: String -> [Constr] -> Maybe (String, Constr) match _ [] = Nothing match input (con:cons) | take n input == showConstr con = Just (drop n input, con) | otherwise = match input cons where n = length (showConstr con) readM :: forall a. Data a => DecM a readM = read where read :: DecM a read = do { let val = argOf read ; let ty = dataTypeOf val ; constr <- parseConstr ty ; let con::a = fromConstr constr ; gmapM (\_ -> readM) con } argOf :: c a -> a argOf = undefined yareadM :: forall a. Data a => DecM a yareadM = do { let ty = dataTypeOf (undefined::a) ; constr <- parseConstr ty ; let con::a = fromConstr constr ; gmapM (\_ -> yareadM) con }