-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Avoiding the C preprocessor via cunning use of Template Haskell -- -- notcpp is a library that attempts to provide an alternative to using -- CPP as a mechanism for conditional compilation. It provides facilities -- for determining if specific names or class instances exist and -- responding accordingly. -- -- When a value or class instance appears between minor releases of a -- third-party package, a common way of dealing with the problem is to -- use CPP to conditionally use one block of code or another. The trouble -- with CPP is it's hard to statically analyse: tools based on -- haskell-src-exts will outright refuse to parse it, for example. It -- turns out Template Haskell will do the same job in some cases. -- -- notcpp is largely a proof-of-concept, experimental package: you are -- welcome to use it if it suits you, but it may be liable to change -- suddenly. @package notcpp @version 0.2 -- | This module uses scope lookup techniques to either export -- lookupValueName from Language.Haskell.TH, or define -- its own lookupValueName, which attempts to do the same job with -- just reify. This will sometimes fail, but if it succeeds it -- will give the answer that the real function would have given. -- -- The idea is that if you use lookupValueName from this module, your -- client code will automatically use the best available name lookup -- mechanism. This means that e.g. scopeLookup can work very -- well on recent GHCs and less well but still somewhat usefully on older -- GHCs. module NotCPP.LookupValueName lookupValueName :: String -> Q (Maybe Name) -- | This module exports scopeLookup, which will find a variable or -- value constructor for you and present it for your use. E.g. at some -- point in the history of the acid-state package, openAcidState -- was renamed openLocalState; for compatibility with both, you -- could use: -- --
--   openState :: IO (AcidState st)
--   openState = case $(scopeLookup "openLocalState") of
--     Just open -> open defaultState
--     Nothing -> case $(scopeLookup "openAcidState") of
--       Just open -> open defaultState
--       Nothing -> error
--         "openState: runtime name resolution has its drawbacks :/"
--   
-- -- Or, for this specific case, you can use scopeLookups: -- --
--   openState :: IO (AcidState st)
--   openState = open defaultState
--    where
--     open = $(scopeLookups ["openLocalState","openAcidState"])
--   
-- -- Now if neither of the names are found then TH will throw a -- compile-time error. module NotCPP.ScopeLookup -- | Produces a spliceable expression which expands to Just -- val if the given string refers to a value val in scope, -- or Nothing otherwise. -- --
--   scopeLookup = fmap liftMaybe . scopeLookup'
--   
scopeLookup :: String -> Q Exp -- | Finds the first string in the list that names a value, and produces a -- spliceable expression of that value, or reports a compile error if it -- fails. scopeLookups :: [String] -> Q Exp -- | Produces Just x if the given string names the value -- x, or Nothing otherwise. scopeLookup' :: String -> Q (Maybe Exp) -- | Turns Nothing into an expression representing Nothing, -- and Just x into an expression representing Just -- applied to the expression in x. liftMaybe :: Maybe Exp -> Exp -- | Turns a possibly-failing Q action into one returning a -- Maybe value. recoverMaybe :: Q a -> Q (Maybe a) -- | A useful variant of reify that returns Nothing instead -- of halting compilation when an error occurs (e.g. because the given -- name was not in scope). maybeReify :: Name -> Q (Maybe Info) -- | Returns Just (VarE n) if the info relates to a -- value called n, or Nothing if it relates to a -- different sort of thing. infoToExp :: Info -> Maybe Exp -- | The orphan instance problem is well-known in Haskell. This module by -- no means purports to solve the problem, but provides a workaround that -- may be significantly less awful than the status quo in some cases. -- -- Say I think that the Name type should have an IsString -- instance. But I don't control either the class or the type, so if I -- define the instance, and then the template-haskell package defines -- one, my code is going to break. -- -- safeInstance can help me to solve this problem: -- --
--   safeInstance ''IsString [t| Name |] [d|
--     fromString = mkName |]
--   
-- -- This will declare an instance only if one doesn't already exist. Now -- anyone importing your module is guaranteed to get an instance one way -- or the other. -- -- This module is still highly experimental. The example given above does -- work, but anything involving type variables or complex method bodies -- may be less fortunate. The names of the methods are mangled a bit, so -- using recursion to define them may not work. Define the method outside -- the code and then use a simple binding as above. -- -- If you use this code (successfully or unsuccessfully!), go fetch the -- maintainer address from the cabal file and let me know! module NotCPP.OrphanEvasion -- | An empty type used only to signify a multiparameter typeclass in -- safeInstance. data MultiParams a -- | safeInstance is a more convenient version of -- safeInstance' that takes the context and type from a -- Q Type with the intention that it be supplied -- using a type-quote. -- -- To define an instance Show a => Show (Wrapper a), you'd -- use: -- --
--   safeInstance ''Show [t| Show a => Wrapper a |]
--     [d| show _ = "stuff" |]
--   
-- -- To define an instance of a multi-param type class, use the -- MultiParams type constructor with a tuple: -- --
--   safeInstance ''MonadState
--     [t| MonadState s m => MultiParams (s, MaybeT m) |]
--     [d| put = ... |]
--   
safeInstance :: Name -> Q Type -> Q [Dec] -> Q [Dec] -- | safeInstance' className cxt types methods produces an -- instance of the given class if and only if one doesn't already exist. -- -- See safeInstance for a simple way to construct the Cxt -- and [Type] parameters. safeInstance' :: Name -> Cxt -> [Type] -> Q [Dec] -> Q [Dec]