git.iko.soy/typeable/servant
on master help sign in
Redundant import fixes
92b1196Julian K. Arni
servant-docs/src/Servant/Docs/Internal.hs−2
@@ -37,13 +37,11 @@ import Data.Ord (comparing)
37import Data.Proxy (Proxy(Proxy))
37import Data.Proxy (Proxy(Proxy))
38import Data.String.Conversions (cs)
38import Data.String.Conversions (cs)
39import Data.Text (Text, unpack)
39import Data.Text (Text, unpack)
40−import GHC.Exts (Constraint)
41import GHC.Generics
40import GHC.Generics
42import GHC.TypeLits
41import GHC.TypeLits
43import Servant.API
42import Servant.API
44import Servant.API.ContentTypes
43import Servant.API.ContentTypes
45import Servant.API.TypeLevel
44import Servant.API.TypeLevel
46−import Servant.Utils.Links
47
45
48import qualified Data.HashMap.Strict as HM
46import qualified Data.HashMap.Strict as HM
49import qualified Data.Text as T
47import qualified Data.Text as T
servant-foreign/src/Servant/Foreign/Internal.hs−1
@@ -16,7 +16,6 @@ import Data.Proxy
16import Data.String
16import Data.String
17import Data.Text
17import Data.Text
18import Data.Text.Encoding (decodeUtf8)
18import Data.Text.Encoding (decodeUtf8)
19−import GHC.Exts (Constraint)
20import GHC.TypeLits
19import GHC.TypeLits
21import qualified Network.HTTP.Types as HTTP
20import qualified Network.HTTP.Types as HTTP
22import Prelude hiding (concat)
21import Prelude hiding (concat)
servant/src/Servant/API/TypeLevel.hs+54−3
@@ -1,8 +1,11 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE KindSignatures #-}
3{-# LANGUAGE KindSignatures #-}
3{-# LANGUAGE PolyKinds #-}
4{-# LANGUAGE PolyKinds #-}
4{-# LANGUAGE TypeFamilies #-}
5{-# LANGUAGE TypeFamilies #-}
5{-# LANGUAGE TypeOperators #-}
6{-# LANGUAGE TypeOperators #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE UndecidableInstances #-}
9{-# LANGUAGE UndecidableInstances #-}
7module Servant.API.TypeLevel where
10module Servant.API.TypeLevel where
8
11
@@ -14,6 +17,9 @@ import Servant.API.Header ( Header )
14import Servant.API.Verbs ( Verb )
17import Servant.API.Verbs ( Verb )
15import Servant.API.Sub ( type (:>) )
18import Servant.API.Sub ( type (:>) )
16import Servant.API.Alternative ( type (:<|>) )
19import Servant.API.Alternative ( type (:<|>) )
20+#if MIN_VERSION_base(4,9,0)
21+import GHC.TypeLits (TypeError, ErrorMessage(..))
22+#endif
17
23
18-- * API predicates
24-- * API predicates
19
25
@@ -104,9 +110,24 @@ type family IsSubList a b :: Constraint where
104 IsSubList '[] b = ()
110 IsSubList '[] b = ()
105 IsSubList (x ': xs) y = Elem x y `And` IsSubList xs y
111 IsSubList (x ': xs) y = Elem x y `And` IsSubList xs y
106
112
113+-- | Check that an eleme is an element of a list:
114+--
115+-- >>> ok (Proxy :: Proxy (Elem Bool '[Int, Bool]))
116+-- OK
117+--
118+-- >>> ok (Proxy :: Proxy (Elem String '[Int, Bool]))
119+-- ...
120+-- No instance for (ElemNotFoundIn [Char] '[Int, Bool])
121+-- arising from a use of ‘ok’
122+-- ...
123+type Elem e es = ElemGo e es es
124+
125+-- 'orig' is used to store original list for better error messages
107−type family Elem e es :: Constraint where
126+type family ElemGo e es orig :: Constraint where
108− Elem x (x ': xs) = ()
127+ ElemGo x (x ': xs) orig = ()
109− Elem y (x ': xs) = Elem y xs
128+ ElemGo y (x ': xs) orig = ElemGo y xs orig
129+ ElemGo x '[] orig = ElemNotFoundIn x orig
130+
110
131
111-- ** Logic
132-- ** Logic
112
133
@@ -121,3 +142,33 @@ type family Or (a :: Constraint) (b :: Constraint) :: Constraint where
121type family And (a :: Constraint) (b :: Constraint) :: Constraint where
142type family And (a :: Constraint) (b :: Constraint) :: Constraint where
122 And () () = ()
143 And () () = ()
123
144
145+-- * Custom type errors
146+
147+#if MIN_VERSION_base(4,9,0)
148+-- GHC >= 8
149+
150+
151+type ElemNotFoundIn val list = TypeError
152+ (ShowType val :<>: Text " expected in list " :<>: ShowList list)
153+
154+
155+-- Utilities
156+
157+type family ShowListGo ls :: ErrorMessage where
158+ ShowListGo '[] = Text ""
159+ ShowListGo (x ': xs) = ShowType x :<>: Text ", " :<>: ShowListGo xs
160+
161+type ShowList ls = Text "[" :<>: ShowListGo ls :<>: Text "]"
162+
163+
164+#else
165+
166+-- GHC < 8
167+class ElemNotFoundIn val list
168+
169+#endif
170+
171+-- $setup
172+-- >>> import Data.Proxy
173+-- >>> data OK = OK deriving (Show)
174+-- >>> let ok :: ctx => Proxy ctx -> OK; ok _ = OK
servant/test/Servant/Utils/LinksSpec.hs−1
@@ -10,7 +10,6 @@ import Test.Hspec (Expectation, Spec, describe, it,
10import Data.String (fromString)
10import Data.String (fromString)
11
11
12import Servant.API
12import Servant.API
13−import Servant.API.TypeLevel
14
13
15type TestApi =
14type TestApi =
16 -- Capture and query params
15 -- Capture and query params