1 -----------------------------------------------------------------------------
3 -- Module : Data.Generics.Strings
4 -- Copyright : (c) The University of Glasgow, CWI 2001--2003
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : non-portable
11 -- "Scrap your boilerplate" --- Generic programming in Haskell
12 -- See <http://www.cs.vu.nl/boilerplate/>.
14 -----------------------------------------------------------------------------
16 module Data.Generics.Strings (
18 -- * Generic operations for string representations of terms
24 ------------------------------------------------------------------------------
29 import Data.Generics.Basics
30 import Data.Generics.Aliases
34 -- | Generic show: an alternative to \"deriving Show\"
35 gshow :: Data a => a -> String
37 -- This is a prefix-show using surrounding "(" and ")",
38 -- where we recurse into subterms with gmapQ.
42 ++ conString (toConstr t)
43 ++ concat (gmapL ((++) " " . gshow) t)
45 ) `extQ` (show :: String -> String)
48 -- | The type constructor for gunfold a la ReadS from the Prelude;
49 -- we don't use lists here for simplicity but only maybes.
51 newtype GRead a = GRead (String -> Maybe (a, String))
55 -- | Turn GRead into a monad.
56 instance Monad GRead where
57 return x = GRead (\s -> Just (x, s))
58 (GRead f) >>= g = GRead (\s ->
60 (\(a,s') -> unGRead (g a) s')
65 -- | Generic read: an alternative to \"deriving Read\"
66 gread :: GenericB Maybe
70 This is a read operation which insists on prefix notation. (The
71 Haskell 98 read deals with infix operators as well. We will be able to
72 deal with such special cases as well as sonn as we include fixity
73 information into the definition of "Constr".) We use gunfold to
74 "parse" the input. To be precise, gunfold is used for all result types
75 except String. The type-specific case for String uses basic String
76 read. Another source of customisation would be to properly deal with
77 infix operators subject to the capture of that information in the
78 definition of Constr. The "gread" combinator properly checks the
79 validity of constructors before invoking gunfold in order to rule
91 -- a specific case for strings
92 scase s = case reads s of
93 [x::(String,String)] -> Just x
96 -- the generic default of gread
97 gdefault s = undefined
102 do s' <- return $ dropWhile ((==) ' ') s
103 guard (not (s' == ""))
104 guard (head s' == '(')
105 (c,s'') <- prefixConstr (dropWhile ((==) ' ') (tail s'))
106 u <- return undefined
107 dt <- return $ dataTypeOf u
108 case stringCon dt c of
109 Nothing -> error "Generics: gread failed"
113 guard ( or [ maxConIndex (dataTypeOf u) == 0
114 , c `elem` constrsOf u
117 (a,s''') <- unGRead (gunfold f z c) s''
118 _ <- return $ constrainTypes a u
119 guard (not (s''' == ""))
120 guard (head s''' == ')')
121 return (a, tail s''')
124 -- To force two types to be the same
125 constrainTypes :: a -> a -> ()
126 constrainTypes _ _ = ()
128 -- Argument f for unfolding
129 f :: Data a => GRead (a -> b) -> GRead b
130 f x = GRead (\s -> do (r,s') <- unGRead x s
134 -- Argument z for unfolding
135 z :: forall g. g -> GRead g
136 z g = GRead (\s -> return (g,s))
139 -- Get Constr at front of string
140 prefixConstr :: String -> Maybe (Constr, String)
142 -- Assume an infix operators in parantheses
144 = case break ((==) ')') s of
145 (s'@(_:_),(')':s'')) -> Just (Constr ("(" ++ s' ++ ")"), s'')
148 -- Special treatment of multiple token constructors
149 prefixConstr ('[':']':s) = Just (Constr "[]",s)
151 -- Try lex for ordinary constructor and basic datatypes
154 [(s'@(_:_),s'')] -> Just (Constr s',s'')