chrisdone/lucid — pull request #10 by athanclark (2014-12-08 03:40:40+00:00)
Title: Url

Created some Url handling primatives:

```haskell
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}

import Lucid
import Lucid.Base
import Lucid.Path
import qualified Data.Text as T
import qualified Data.Text.Lazy as LT

import Data.Functor.Identity

template :: Url UrlString f => HtmlT f ()
template = do
url <- lift $ renderUrl $ "foo.php" ("key","bar") <&> ("key2","baz")
script_ [src_ url] ""

example :: UrlReader m => HtmlT m () -> LT.Text
example x = (runUrlReader $ renderTextT x) "example.com"

relative :: HtmlT RelativeUrl ()
relative = template

relative' :: LT.Text
relative' = example relative

grounded :: HtmlT GroundedUrl ()
grounded = template

grounded' :: LT.Text
grounded' = example grounded

absolute :: HtmlT AbsoluteUrl ()
absolute = template

absolute' :: LT.Text
absolute' = example absolute
```

Here's some Transformers stuff, too:

```haskell
exampleT :: (MonadReader T.Text (f m), Monad m) =>
HtmlT (f m) ()
-> (f m T.Text -> T.Text -> m T.Text) -- ^ `run*` for a T.Text based MonadReader
-> m T.Text
exampleT x f = (f $ renderTextT x) "example.com"

relativeT :: Monad m => HtmlT (RelativeUrlT m) ()
relativeT = template

relativeT' :: LT.Text
relativeT' = runIdentity $ exampleT relativeT runRelativeUrlT
```

Basically, the idea is that every Url lives in a reader monad. To make a Url render with a particular Url Scheme (ie: relative, grounded, or absolute), you just coerce it's monad reader. Three monad readers were made for coercing - `RelativeUrl`, `GroundedUrl`, and `AbsoluteUrl`. Both relative and grounded urls have dummy, `const`-like `MonadReader` instances, but it gives us a nice and uniform API. What do you think? I hope this is good enough :)

Also, here's an example with plaintext:

```haskell
plain :: HtmlT Identity ()
plain = do
url <- renderUrl ("foo.php" :: T.Text)
script_ [src_ url] ""

plain' :: LT.Text
plain' = renderText plain
```