module UrlPath.Types where
import Data.String
import Data.Monoid
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Reader.Class
data UrlString a where
UrlString :: ( IsString a
, Monoid a ) =>
a
-> [(a, a)]
-> UrlString a
showUrlString :: UrlString a
-> a
showUrlString (UrlString !t []) = t
showUrlString (UrlString !t ((!k,!v):xs)) =
t <> "?" <> k <> "=" <> v <>
foldl (\acc (x,y) -> acc <> "&" <> x <> "=" <> y) "" xs
(<?>) :: ( IsString a
, Monoid a ) =>
a
-> (a, a)
-> UrlString a
(<?>) !t !kv = UrlString t [kv]
infixl 9 <?>
(<&>) :: ( IsString a
, Monoid a ) =>
UrlString a
-> (a, a)
-> UrlString a
(<&>) (UrlString !t !p) !kv = UrlString t $ p ++ [kv]
infixl 8 <&>
expandRelative :: ( IsString a
, Monoid a ) =>
UrlString a
-> a
expandRelative = showUrlString
expandGrounded :: ( IsString a
, Monoid a ) =>
UrlString a
-> a
expandGrounded !x = "/" <> showUrlString x
expandAbsolute :: ( MonadReader a m
, IsString a
, Monoid a ) =>
UrlString a
-> m a
expandAbsolute !x = do
host <- ask
return $ host <> "/" <> showUrlString x
expandAbsoluteWith :: ( MonadReader a m
, IsString a
, Monoid a ) =>
UrlString a
-> (a -> a)
-> m a
expandAbsoluteWith !x f = do
root <- liftM f ask
return $ root <> "/" <> showUrlString x
newtype RelativeUrlT h m a = RelativeUrlT { runRelativeUrlT :: h -> m a }
deriving Functor
instance Applicative f => Applicative (RelativeUrlT h f) where
(<*>) f x = RelativeUrlT $ \a ->
(<*>) (runRelativeUrlT f a) (runRelativeUrlT x a)
instance Monad m => Monad (RelativeUrlT h m) where
return x = RelativeUrlT $ \_ -> return x
m >>= f = RelativeUrlT $ \a ->
runRelativeUrlT m a >>= (\x -> runRelativeUrlT (f x) a)
instance MonadTrans (RelativeUrlT h) where
lift m = RelativeUrlT (const m)
instance ( Monad m
, IsString a ) => MonadReader a (RelativeUrlT a m) where
ask = return ""
instance MonadIO m => MonadIO (RelativeUrlT a m) where
liftIO = lift . liftIO
newtype RelativeUrl h a = RelativeUrl { runRelativeUrl :: h -> a }
deriving Functor
instance Applicative (RelativeUrl h) where
(<*>) f x = RelativeUrl $ \a ->
runRelativeUrl f a (runRelativeUrl x a)
instance Monad (RelativeUrl h) where
return x = RelativeUrl $ const x
m >>= f = RelativeUrl $ \a ->
(\y -> runRelativeUrl (f y) a) (runRelativeUrl m a)
instance IsString a => MonadReader a (RelativeUrl a) where
ask = return ""
newtype GroundedUrlT h m a = GroundedUrlT { runGroundedUrlT :: h -> m a }
instance Functor f => Functor (GroundedUrlT h f) where
fmap f x = GroundedUrlT $ \a ->
fmap f (runGroundedUrlT x a)
instance Applicative f => Applicative (GroundedUrlT h f) where
(<*>) f x = GroundedUrlT $ \a ->
(<*>) (runGroundedUrlT f a) (runGroundedUrlT x a)
instance Monad m => Monad (GroundedUrlT h m) where
return x = GroundedUrlT $ \_ -> return x
m >>= f = GroundedUrlT $ \a ->
runGroundedUrlT m a >>= (\x -> runGroundedUrlT (f x) a)
instance MonadTrans (GroundedUrlT h) where
lift m = GroundedUrlT (const m)
instance ( Monad m
, IsString a ) => MonadReader a (GroundedUrlT a m) where
ask = return "/"
instance MonadIO m => MonadIO (GroundedUrlT a m) where
liftIO = lift . liftIO
newtype GroundedUrl h a = GroundedUrl { runGroundedUrl :: h -> a }
instance Functor (GroundedUrl h) where
fmap f x = GroundedUrl $ \a -> f $ runGroundedUrl x a
instance Applicative (GroundedUrl h) where
(<*>) f x = GroundedUrl $ \a ->
runGroundedUrl f a (runGroundedUrl x a)
instance Monad (GroundedUrl h) where
return x = GroundedUrl $ const x
m >>= f = GroundedUrl $ \a ->
(\y -> runGroundedUrl (f y) a) (runGroundedUrl m a)
instance IsString a => MonadReader a (GroundedUrl a) where
ask = return "/"
newtype AbsoluteUrlT h m a = AbsoluteUrlT { runAbsoluteUrlT :: h -> m a }
instance Functor f => Functor (AbsoluteUrlT h f) where
fmap f x = AbsoluteUrlT $ \a ->
fmap f (runAbsoluteUrlT x a)
instance Applicative f => Applicative (AbsoluteUrlT h f) where
(<*>) f x = AbsoluteUrlT $ \a ->
(<*>) (runAbsoluteUrlT f a) (runAbsoluteUrlT x a)
instance Monad m => Monad (AbsoluteUrlT h m) where
return x = AbsoluteUrlT $ const $ return x
m >>= f = AbsoluteUrlT $ \a ->
runAbsoluteUrlT m a >>= (\x -> runAbsoluteUrlT (f x) a)
instance MonadTrans (AbsoluteUrlT h) where
lift m = AbsoluteUrlT (const m)
instance ( Monad m
, IsString a ) => MonadReader a (AbsoluteUrlT a m) where
ask = AbsoluteUrlT return
instance MonadIO m => MonadIO (AbsoluteUrlT a m) where
liftIO = lift . liftIO
newtype AbsoluteUrl h a = AbsoluteUrl { runAbsoluteUrl :: h -> a }
instance Functor (AbsoluteUrl h) where
fmap f x = AbsoluteUrl $ \a -> f $ runAbsoluteUrl x a
instance Applicative (AbsoluteUrl h) where
(<*>) f x = AbsoluteUrl $ \a ->
runAbsoluteUrl f a (runAbsoluteUrl x a)
instance Monad (AbsoluteUrl h) where
return x = AbsoluteUrl $ const x
m >>= f = AbsoluteUrl $ \a ->
(\y -> runAbsoluteUrl (f y) a) (runAbsoluteUrl m a)
instance IsString a => MonadReader a (AbsoluteUrl a) where
ask = AbsoluteUrl id