on master help sign in
add the Canonicalize type family which turns an API type into its canonical form
commit73914586b1384b041e47da7349b1fd29a4012e9c authorAlp Mestanogullari <alpmestan@gmail.com> dateMon 9 Mar 2015, 13:39 (12 years ago) parent13dcf08
1 file changed+28
src/Servant/API.hs+28
src/Servant/API.hs+28
@@ -1,3 +1,6 @@
1+{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE TypeOperators #-}
3+{-# LANGUAGE UndecidableInstances #-}
14module Servant.API (
25
36 -- * Combinators
@@ -43,6 +46,9 @@ module Servant.API (
4346 module Servant.Common.Text,
4447 -- | Classes and instances for types that can be converted to and from @Text@
4548
49+ -- * Canonicalizing (flattening) API types
50+ Canonicalize,
51+
4652 -- * Utilities
4753 module Servant.Utils.Links,
4854 -- | Type-safe internal URIs
@@ -69,3 +75,25 @@ import Servant.API.ReqBody (ReqBody)
6975import Servant.API.Sub ((:>))
7076import Servant.Utils.Links (HasLink (..), IsElem, IsElem',
7177 URI (..), safeLink)
78+
79+-- | Turn an API type into its canonical form.
80+--
81+-- The canonical form is defined and will basically turn:
82+--
83+-- > "hello" :> (Get Hello :<|> ReqBody Hello :> Put Hello)
84+--
85+-- into
86+--
87+-- > ("hello" :> Get Hello) :<|> ("hello" :> ReqBody Hello :> Put Hello)
88+--
89+-- i.e distributing all ':>'-separated bits into the subsequent ':<|>'s.
90+type family Canonicalize api :: * where
91+ -- requires UndecidableInstances
92+ Canonicalize (a :> (b :<|> c)) = ((a :> Canonicalize b) :<|> (a :> Canonicalize c))
93+ Canonicalize (a :> b) = Redex b (Canonicalize b) a
94+ Canonicalize (a :<|> b) = Canonicalize a :<|> Canonicalize b
95+ Canonicalize a = a
96+
97+type family Redex a b c :: * where
98+ Redex a a first = Canonicalize first :> a
99+ Redex a b first = Canonicalize (first :> b)