@@ -6,7 +6,6 @@
6{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE TypeFamilies #-}
7{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeOperators #-}
8{-# LANGUAGE TypeOperators #-}
9−{-# LANGUAGE UndecidableInstances #-}
10{-# OPTIONS_HADDOCK not-home #-}
9{-# OPTIONS_HADDOCK not-home #-}
12-- | Type safe generation of internal links.
11-- | Type safe generation of internal links.
@@ -79,6 +78,8 @@
79-- bad_link under api after trying the open (but empty) type family
78-- bad_link under api after trying the open (but empty) type family
80-- `IsElem'` as a last resort.
79-- `IsElem'` as a last resort.
81module Servant.Utils.Links (
80module Servant.Utils.Links (
81+ module Servant.API.TypeLevel,
82 -- * Building and using safe links
83 -- * Building and using safe links
84 -- | Note that 'URI' is Network.URI.URI from the network-uri package.
85 -- | Note that 'URI' is Network.URI.URI from the network-uri package.
@@ -88,10 +89,6 @@ module Servant.Utils.Links (
88 , HasLink(..)
89 , HasLink(..)
92− -- * Illustrative exports
97import Data.List
94import Data.List
@@ -99,7 +96,6 @@ import Data.Monoid.Compat ( (<>) )
99import Data.Proxy ( Proxy(..) )
96import Data.Proxy ( Proxy(..) )
100import qualified Data.Text as Text
97import qualified Data.Text as Text
101import qualified Data.Text.Encoding as TE
98import qualified Data.Text.Encoding as TE
102−import GHC.Exts (Constraint)
103import GHC.TypeLits ( KnownSymbol, symbolVal )
99import GHC.TypeLits ( KnownSymbol, symbolVal )
104import Network.URI ( URI(..), escapeURIString, isUnreserved )
100import Network.URI ( URI(..), escapeURIString, isUnreserved )
105import Prelude ()
101import Prelude ()
@@ -115,7 +111,7 @@ import Servant.API.RemoteHost ( RemoteHost )
115import Servant.API.Verbs ( Verb )
111import Servant.API.Verbs ( Verb )
116import Servant.API.Sub ( type (:>) )
112import Servant.API.Sub ( type (:>) )
117import Servant.API.Raw ( Raw )
113import Servant.API.Raw ( Raw )
118−import Servant.API.Alternative ( type (:<|>) )
114+import Servant.API.TypeLevel
120-- | A safe link datatype.
116-- | A safe link datatype.
121-- The only way of constructing a 'Link' is using 'safeLink', which means any
117-- The only way of constructing a 'Link' is using 'safeLink', which means any
@@ -131,58 +127,6 @@ instance ToHttpApiData Link where
131 let uri = linkURI l
127 let uri = linkURI l
132 in Text.pack $ uriPath uri ++ uriQuery uri
128 in Text.pack $ uriPath uri ++ uriQuery uri
134−-- | If either a or b produce an empty constraint, produce an empty constraint.
135−type family Or (a :: Constraint) (b :: Constraint) :: Constraint where
136− -- This works because of:
137− -- https://ghc.haskell.org/trac/ghc/wiki/NewAxioms/CoincidentOverlap
141−-- | If both a or b produce an empty constraint, produce an empty constraint.
142−type family And (a :: Constraint) (b :: Constraint) :: Constraint where
145−-- | You may use this type family to tell the type checker that your custom
146−-- type may be skipped as part of a link. This is useful for things like
147−-- 'QueryParam' that are optional in a URI and do not affect them if they are
150−-- >>> data CustomThing
151−-- >>> type instance IsElem' e (CustomThing :> s) = IsElem e s
153−-- Note that 'IsElem' is called, which will mutually recurse back to `IsElem'`
154−-- if it exhausts all other options again.
156−-- Once you have written a HasLink instance for CustomThing you are ready to
158−type family IsElem' a s :: Constraint
160−-- | Closed type family, check if endpoint is within api
161−type family IsElem endpoint api :: Constraint where
162− IsElem e (sa :<|> sb) = Or (IsElem e sa) (IsElem e sb)
163− IsElem (e :> sa) (e :> sb) = IsElem sa sb
164− IsElem sa (Header sym x :> sb) = IsElem sa sb
165− IsElem sa (ReqBody y x :> sb) = IsElem sa sb
166− IsElem (Capture z y :> sa) (Capture x y :> sb)
168− IsElem (CaptureAll z y :> sa) (CaptureAll x y :> sb)
170− IsElem sa (QueryParam x y :> sb) = IsElem sa sb
171− IsElem sa (QueryParams x y :> sb) = IsElem sa sb
172− IsElem sa (QueryFlag x :> sb) = IsElem sa sb
173− IsElem (Verb m s ct typ) (Verb m s ct' typ)
176− IsElem e a = IsElem' e a
178−type family IsSubList a b :: Constraint where
179− IsSubList '[] b = ()
180− IsSubList (x ': xs) y = Elem x y `And` IsSubList xs y
182−type family Elem e es :: Constraint where
183− Elem x (x ': xs) = ()
184− Elem y (x ': xs) = Elem y xs
186-- Phantom types for Param
130-- Phantom types for Param
187data Query
131data Query