module UrlPath.Types where
import qualified Data.Text as T
import Data.Monoid
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Reader.Class
data GETParam = GETParam { key :: !T.Text
, val :: !T.Text
}
deriving (Show, Eq)
renderGETParam :: GETParam
-> T.Text
renderGETParam (GETParam k v) =
"&" <> k <> "=" <> v
data UrlString = UrlString { target :: !T.Text
, params :: [GETParam]
}
deriving (Show, Eq)
renderUrlString :: UrlString
-> T.Text
renderUrlString (UrlString t []) = t
renderUrlString (UrlString t [GETParam k v]) =
t <> "?" <> k <> "=" <> v
renderUrlString (UrlString t (GETParam k v : ps)) =
t <> "?" <> k <> "=" <> v <>
foldr (\x acc -> acc <> renderGETParam x) "" ps
(<?>) :: T.Text
-> (T.Text, T.Text)
-> UrlString
t <?> (k,v) = UrlString t [GETParam k v]
infixl 9 <?>
(<&>) :: UrlString
-> (T.Text, T.Text)
-> UrlString
old <&> (k,v) = UrlString (target old) $ params old ++ [GETParam k v]
infixl 8 <&>
expandRelative :: UrlString
-> T.Text
expandRelative = renderUrlString
expandGrounded :: UrlString
-> T.Text
expandGrounded x = "/" <> renderUrlString x
expandAbsolute :: (MonadReader T.Text m) =>
UrlString
-> m T.Text
expandAbsolute x = do
root <- ask
return $ root <> "/" <> renderUrlString x
expandAbsoluteWith :: (MonadReader a m) =>
UrlString
-> (a -> T.Text)
-> m T.Text
expandAbsoluteWith x f = do
root <- liftM f ask
return $ root <> "/" <> renderUrlString x
newtype RelativeUrlT m a = RelativeUrlT { runRelativeUrlT :: T.Text -> m a }
instance Functor f => Functor (RelativeUrlT f) where
fmap f x = RelativeUrlT $ \a ->
fmap f (runRelativeUrlT x a)
instance Applicative f => Applicative (RelativeUrlT f) where
(<*>) f x = RelativeUrlT $ \a ->
(<*>) (runRelativeUrlT f a) (runRelativeUrlT x a)
instance Monad m => Monad (RelativeUrlT m) where
return x = RelativeUrlT $ \_ -> return x
m >>= f = RelativeUrlT $ \a ->
runRelativeUrlT m a >>= (\x -> runRelativeUrlT (f x) a)
instance MonadTrans RelativeUrlT where
lift m = RelativeUrlT (const m)
instance Monad m => MonadReader T.Text (RelativeUrlT m) where
ask = return ""
newtype RelativeUrl a = RelativeUrl { runRelativeUrl :: T.Text -> a }
instance Functor RelativeUrl where
fmap f x = RelativeUrl $ \a -> f $ runRelativeUrl x a
instance Applicative RelativeUrl where
(<*>) f x = RelativeUrl $ \a ->
runRelativeUrl f a (runRelativeUrl x a)
instance Monad RelativeUrl where
return x = RelativeUrl $ const x
m >>= f = RelativeUrl $ \a ->
(\y -> runRelativeUrl (f y) a) (runRelativeUrl m a)
instance MonadReader T.Text RelativeUrl where
ask = return ""
newtype GroundedUrlT m a = GroundedUrlT { runGroundedUrlT :: T.Text -> m a }
instance Functor f => Functor (GroundedUrlT f) where
fmap f x = GroundedUrlT $ \a ->
fmap f (runGroundedUrlT x a)
instance Applicative f => Applicative (GroundedUrlT f) where
(<*>) f x = GroundedUrlT $ \a ->
(<*>) (runGroundedUrlT f a) (runGroundedUrlT x a)
instance Monad m => Monad (GroundedUrlT m) where
return x = GroundedUrlT $ \_ -> return x
m >>= f = GroundedUrlT $ \a ->
runGroundedUrlT m a >>= (\x -> runGroundedUrlT (f x) a)
instance MonadTrans GroundedUrlT where
lift m = GroundedUrlT (const m)
instance Monad m => MonadReader T.Text (GroundedUrlT m) where
ask = return "/"
newtype GroundedUrl a = GroundedUrl { runGroundedUrl :: T.Text -> a }
instance Functor GroundedUrl where
fmap f x = GroundedUrl $ \a -> f $ runGroundedUrl x a
instance Applicative GroundedUrl where
(<*>) f x = GroundedUrl $ \a ->
runGroundedUrl f a (runGroundedUrl x a)
instance Monad GroundedUrl where
return x = GroundedUrl $ const x
m >>= f = GroundedUrl $ \a ->
(\y -> runGroundedUrl (f y) a) (runGroundedUrl m a)
instance MonadReader T.Text GroundedUrl where
ask = return "/"
newtype AbsoluteUrlT m a = AbsoluteUrlT { runAbsoluteUrlT :: T.Text -> m a }
instance Functor f => Functor (AbsoluteUrlT f) where
fmap f x = AbsoluteUrlT $ \a ->
fmap f (runAbsoluteUrlT x a)
instance Applicative f => Applicative (AbsoluteUrlT f) where
(<*>) f x = AbsoluteUrlT $ \a ->
(<*>) (runAbsoluteUrlT f a) (runAbsoluteUrlT x a)
instance Monad m => Monad (AbsoluteUrlT m) where
return x = AbsoluteUrlT $ const $ return x
m >>= f = AbsoluteUrlT $ \a ->
runAbsoluteUrlT m a >>= (\x -> runAbsoluteUrlT (f x) a)
instance MonadTrans AbsoluteUrlT where
lift m = AbsoluteUrlT (const m)
instance Monad m => MonadReader T.Text (AbsoluteUrlT m) where
ask = AbsoluteUrlT return
newtype AbsoluteUrl a = AbsoluteUrl { runAbsoluteUrl :: T.Text -> a }
instance Functor AbsoluteUrl where
fmap f x = AbsoluteUrl $ \a -> f $ runAbsoluteUrl x a
instance Applicative AbsoluteUrl where
(<*>) f x = AbsoluteUrl $ \a ->
runAbsoluteUrl f a (runAbsoluteUrl x a)
instance Monad AbsoluteUrl where
return x = AbsoluteUrl $ const x
m >>= f = AbsoluteUrl $ \a ->
(\y -> runAbsoluteUrl (f y) a) (runAbsoluteUrl m a)
instance MonadReader T.Text AbsoluteUrl where
ask = AbsoluteUrl id