-- | The combinators of this library are all pairs of functions going in -- opposite directions. These pairs are called /cassettes/, sporting two -- tracks (the two functions), one of which is read is one direction, the -- other of which (accessed by flipping the cassette) is read in the opossite -- direction. -- -- Here is an example specification for the lambda-calculus: -- -- > varL = K7 leadout leadin where -- > leadout k k' s x = k (\ s _ -> k' s x) s (Var x) -- > leadin k k' s t@(Var x) = k (\ s _ -> k' s t) s x -- > leadin k k' s t = k' s t -- > -- > absL = K7 leadout leadin where -- > leadout k k' s t' x = k (\ s _ -> k' s t' x) s (Lam x t') -- > leadin k k' s t@(Lam x t) = k (\ s _ _ -> k' s t) s t x -- > leadin k k' s t = k' s t -- > -- > appL = K7 leadout leadin where -- > leadout k s t2 t1 = k (\ s _ -> k' s t2 t1) s (App t1 t2) -- > leadin k k' s t@(App t1 t2) = k (\ s _ _ -> k' s t) s t2 t1 -- > leadin k k' s t = k' s t -- > -- > parens p = char '(' <> p <> char ')' -- > -- > term :: PP Term -- > term = varL --> ident -- > <|> absL --> char '\' <> ident <> term -- > <|> appL --> parens (term <> sepSpace <> term) -- -- From this single specification, we can extract a parser, -- -- > parse term :: PP Term -> String -> Maybe Term -- -- and also a pretty printer, -- -- > pretty term :: PP Term -> Term -> Maybe String -- -- Specifications are built from primitive and derived combinators, which -- affect the input string in some way. For each constructor of each datatype, -- we need to write a /lead/, which is a pair of a construction function and a -- destruction function. Leads are pure combinators that do not affect the -- input string. By convention, we suffix their name with "L". -- -- Internally, the primitive combinators are written in CPS. Leads also need -- to be written in this style, being primitive. They can, however, be -- automatically generated for every datatype using some Template Haskell -- hackery (in a separate package). A number of leads for standard datatypes -- are defined in the 'Text.Cassette.Lead' module. module Text.Cassette ( module Text.Cassette.Prim , module Text.Cassette.Lead , module Text.Cassette.Combinator , module Text.Cassette.Char , module Text.Cassette.Number ) where import Text.Cassette.Prim import Text.Cassette.Lead import Text.Cassette.Combinator import Text.Cassette.Char import Text.Cassette.Number