-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Painfully simple URL writing combinators -- -- Simple URL DSL for Haskell. -- -- This library tries to make it easier for people to write Url strings, -- structurally. Packages like Yesod Routes do a wonderful job at -- implementing string-free routing and references, but sometimes we have -- to compromise. This tries to make that compromise less painful. -- -- Use bare combinators to render your strings (kinda useless): -- --
-- expandRelative $ "foo.php" <?> ("key1","bar") <&> ("key2","baz")
--
-- ↪ "foo.php?key1=bar&key2=baz"
--
--
-- ... or use the MonadReader instance for a configurable host:
--
--
-- let path = runAbsoluteUrl $ url $ "foo.php" <?> ("key1","bar") <&> ("key2","baz")
-- path "example.com"
--
-- ↪ "example.com/foo.php?key1=bar&key2=baz"
--
--
-- url puts the UrlString in a MonadReader that we can
-- use for applying our host. We use different monads for different
-- deployment schemes (currently we have 3 - RelativeUrl,
-- GroundedUrl, and AbsoluteUrl), which we can
-- integrate in different libraries, like Lucid:
--
--
-- (runAbsoluteUrl $ renderTextT $ do
-- foo <- lift $ url $ "foo" <?> ("bar","baz")
-- script_ [src_ foo] "" )
-- ) "example.com"
--
-- ↪ "<script src=\"example.com/foo?bar=baz\"></script>"
--
--
-- ... and in Scotty ...
--
--
-- main :: IO ()
-- main = scottyT 3000
-- rootConf
-- rootConf
-- run
--
-- where
-- rootConf = flip runAbsoluteT "http://example.com"
--
-- run :: ( MonadIO m
-- , MonadReader T.Text m
-- , Url T.Text m ) =>
-- ScottyT LT.Text m ()
-- run = get "/" $ do
-- path <- lift $ url $ "foo" <?> ("bar","baz")
-- text $ LT.fromStrict path
--
-- λ> curl localhost:3000/
-- ↪ "http://example.com/foo?bar=baz"
--
--
-- Note that in the scotty example, we don't use one of our deployment
-- schemes - this is because the scottyT function expects it's
-- underlying monad to be an instance of MonadIO, which we can
-- only instantiate in our monad transformers.
--
-- Please take mind - the string type underlying the Url rendering is
-- generalized to Data.String.IsString for convenient use with
-- -XOverloadedStrings. However, due to that generality, we need
-- to specify the monomorphic type (like Data.Text.Text above).
@package urlpath
@version 0.1
module UrlPath.Types
-- | A Url string - a target page and GET parameters. We only require a
-- constraint of IsString so that construction can be
-- convenient, but rendering will require a monomorphic type.
data UrlString a
UrlString :: a -> [(a, a)] -> UrlString a
-- | We choose to not provide a Show instance for
-- UrlString to evade the String demand.
showUrlString :: UrlString a -> a
-- | Lifts a raw target path and a GET parameter pair into a
-- UrlString.
(>) :: (IsString a, Monoid a) => a -> (a, a) -> UrlString a
-- | Adds another GET parameter pair to a UrlString.
(<&>) :: (IsString a, Monoid a) => UrlString a -> (a, a) -> UrlString a
-- | Render the Url String as relative
expandRelative :: (IsString a, Monoid a) => UrlString a -> a
-- | Render the Url String as grounded
expandGrounded :: (IsString a, Monoid a) => UrlString a -> a
-- | Render the Url String as absolute - getting the root from a
-- MonadReader context. The Monoid instance will be
-- decided monomorphically, therefore a type signature will be needed
-- when ran.
expandAbsolute :: (MonadReader a m, IsString a, Monoid a) => UrlString a -> m a
-- | Render the Url String as absolute, but with your own configuration
-- type.
--
--
-- data SiteConfig = SiteConfig { host :: T.Text
-- , cdnHost :: T.Text
-- }
-- deriving (Show, Eq)
--
-- foo :: HtmlT (Reader SiteConfig) ()
-- foo = do
-- url <- lift $ expandAbsoluteWith ("foo.php" <?> ("bar","baz")) host
-- script_ [src_ url] ""
--
-- bar :: LT.Text
-- bar = (runReader (runTextT foo)) $
-- SiteConfig "example.com" "cdn.example.com"
--
expandAbsoluteWith :: (MonadReader a m, IsString a, Monoid a) => UrlString a -> (a -> a) -> m a
-- | Rendering mode transformer. This isn't an instance of
-- UrlReader - to use, simple lift as many levels as
-- you need:
--
--
-- foo :: Monad m => HtmlT (RelativeUrlT m) ()
-- foo = do
-- path <- lift $ url $ "foo.php" <?> ("bar","baz")
-- script_ [src_ path] ""
--
--
-- When rendering foo, simply use the Transformer's run
-- function to convert it to a reader:
--
-- -- bar :: ( Monad m, IsString a, Monoid a ) => m a -- bar = (runRelativeUrlT (renderTextT foo)) "example.com" --newtype RelativeUrlT h m a RelativeUrlT :: (h -> m a) -> RelativeUrlT h m a runRelativeUrlT :: RelativeUrlT h m a -> h -> m a -- | Concrete Monad for automatically coercing HtmlT's to use a mode of Url -- rendering (relative, grounded, or absolute). -- --
-- foo :: HtmlT RelativeUrl ()
-- foo = do
-- path <- lift $ url $ "foo.php" <?> ("bar","baz")
-- script_ [src_ path] ""
--
--
-- when running the monad reader, use the runUrlReader member
-- function of the UrlReader typeclass:
--
-- -- bar :: ( IsString a, Monoid a ) => a -- bar = (runUrlReader (renderTextT foo)) "example.com" ---- -- To change the deployment sheme, simply coerce the environment monad in -- foo. newtype RelativeUrl h a RelativeUrl :: (h -> a) -> RelativeUrl h a runRelativeUrl :: RelativeUrl h a -> h -> a newtype GroundedUrlT h m a GroundedUrlT :: (h -> m a) -> GroundedUrlT h m a runGroundedUrlT :: GroundedUrlT h m a -> h -> m a newtype GroundedUrl h a GroundedUrl :: (h -> a) -> GroundedUrl h a runGroundedUrl :: GroundedUrl h a -> h -> a newtype AbsoluteUrlT h m a AbsoluteUrlT :: (h -> m a) -> AbsoluteUrlT h m a runAbsoluteUrlT :: AbsoluteUrlT h m a -> h -> m a newtype AbsoluteUrl h a AbsoluteUrl :: (h -> a) -> AbsoluteUrl h a runAbsoluteUrl :: AbsoluteUrl h a -> h -> a instance Functor m => Functor (RelativeUrlT h m) instance Functor (RelativeUrl h) instance IsString a => MonadReader a (AbsoluteUrl a) instance Monad (AbsoluteUrl h) instance Applicative (AbsoluteUrl h) instance Functor (AbsoluteUrl h) instance MonadIO m => MonadIO (AbsoluteUrlT a m) instance (Monad m, IsString a) => MonadReader a (AbsoluteUrlT a m) instance MonadTrans (AbsoluteUrlT h) instance Monad m => Monad (AbsoluteUrlT h m) instance Applicative f => Applicative (AbsoluteUrlT h f) instance Functor f => Functor (AbsoluteUrlT h f) instance IsString a => MonadReader a (GroundedUrl a) instance Monad (GroundedUrl h) instance Applicative (GroundedUrl h) instance Functor (GroundedUrl h) instance MonadIO m => MonadIO (GroundedUrlT a m) instance (Monad m, IsString a) => MonadReader a (GroundedUrlT a m) instance MonadTrans (GroundedUrlT h) instance Monad m => Monad (GroundedUrlT h m) instance Applicative f => Applicative (GroundedUrlT h f) instance Functor f => Functor (GroundedUrlT h f) instance IsString a => MonadReader a (RelativeUrl a) instance Monad (RelativeUrl h) instance Applicative (RelativeUrl h) instance MonadIO m => MonadIO (RelativeUrlT a m) instance (Monad m, IsString a) => MonadReader a (RelativeUrlT a m) instance MonadTrans (RelativeUrlT h) instance Monad m => Monad (RelativeUrlT h m) instance Applicative f => Applicative (RelativeUrlT h f) module UrlPath -- | Overload deployment schemes with this - then, all that's needed is a -- type coercion to change deployment. This only works with flat -- (co)monads, so monad transformers are out. class Url string m => UrlReader string m runUrlReader :: (UrlReader string m, Url string m) => m string -> string -> string -- | Url is a relationship between an underlying (monomorphic) -- string type string, and a deployment context m. We -- try to make the deployment and implementation type coercible at the -- top level - coercing your final expression to String or -- T.Text will have all use-cases coerce to that type, -- similarly with the deployment scheme. -- -- We chose to not force MonadReader as a superclass for -- m due to the monomorphic demand on functional dependencies. class (IsString string, Monoid string, MonadReader string m) => Url string (m :: * -> *) url :: Url string m => UrlString string -> m string stringUrl :: Url string m => string -> m string instance (Monad m, Monoid a, IsString a) => Url a (AbsoluteUrlT a m) instance (Monad m, Monoid a, IsString a) => Url a (GroundedUrlT a m) instance (Monad m, Monoid a, IsString a) => Url a (RelativeUrlT a m) instance (Monoid a, IsString a) => UrlReader a (AbsoluteUrl a) instance (Monoid a, IsString a) => Url a (AbsoluteUrl a) instance (Monoid a, IsString a) => UrlReader a (GroundedUrl a) instance (Monoid a, IsString a) => Url a (GroundedUrl a) instance (Monoid a, IsString a) => UrlReader a (RelativeUrl a) instance (Monoid a, IsString a) => Url a (RelativeUrl a)