@@ -4,7 +4,6 @@
4{-# LANGUAGE DeriveDataTypeable #-}
4{-# LANGUAGE DeriveDataTypeable #-}
5{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
7−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
9{-# LANGUAGE OverloadedStrings #-}
8{-# LANGUAGE OverloadedStrings #-}
10{-# LANGUAGE PolyKinds #-}
9{-# LANGUAGE PolyKinds #-}
@@ -14,6 +13,14 @@
14{-# LANGUAGE TypeFamilies #-}
13{-# LANGUAGE TypeFamilies #-}
15{-# LANGUAGE TypeOperators #-}
14{-# LANGUAGE TypeOperators #-}
16+#if MIN_VERSION_base(4,9,0) && __GLASGOW_HASKELL__ >= 802
17+#define HAS_TYPE_ERROR
21+{-# LANGUAGE UndecidableInstances #-}
17#include "overlapping-compat.h"
24#include "overlapping-compat.h"
19module Servant.Server.Internal
26module Servant.Server.Internal
@@ -87,6 +94,9 @@ import Servant.Server.Internal.Router
87import Servant.Server.Internal.RoutingApplication
94import Servant.Server.Internal.RoutingApplication
88import Servant.Server.Internal.ServantErr
95import Servant.Server.Internal.ServantErr
98+import GHC.TypeLits (TypeError, ErrorMessage (..))
91class HasServer api context where
101class HasServer api context where
92 type ServerT api (m :: * -> *) :: *
102 type ServerT api (m :: * -> *) :: *
@@ -703,3 +713,75 @@ instance (HasContextEntry context (NamedContext name subContext), HasServer subA
703 subContext = descendIntoNamedContext (Proxy :: Proxy name) context
713 subContext = descendIntoNamedContext (Proxy :: Proxy name) context
705 hoistServerWithContext _ _ nt s = hoistServerWithContext (Proxy :: Proxy subApi) (Proxy :: Proxy subContext) nt s
715 hoistServerWithContext _ _ nt s = hoistServerWithContext (Proxy :: Proxy subApi) (Proxy :: Proxy subContext) nt s
717+-------------------------------------------------------------------------------
719+-------------------------------------------------------------------------------
721+#ifdef HAS_TYPE_ERROR
722+-- | This instance catches mistakes when there are non-saturated
723+-- type applications on LHS of ':>'.
725+-- >>> serve (Proxy :: Proxy (Capture "foo" :> Get '[JSON] Int)) (error "...")
727+-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
728+-- ...Maybe you haven't applied enough arguments to
732+-- >>> undefined :: Server (Capture "foo" :> Get '[JSON] Int)
734+-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
735+-- ...Maybe you haven't applied enough arguments to
739+instance TypeError (HasServerArrowKindError arr) => HasServer ((arr :: k -> l) :> api) context
741+ type ServerT (arr :> api) m = TypeError (HasServerArrowKindError arr)
742+ -- it doens't really matter what sub route we peak
743+ route _ _ _ = error "servant-server panic: impossible happened in HasServer (arr :> api)"
744+ hoistServerWithContext _ _ _ = id
746+-- Cannot have TypeError here, otherwise use of this symbol will error :)
747+type HasServerArrowKindError arr =
748+ 'Text "Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'."
749+ ':$$: 'Text "Maybe you haven't applied enough arguments to"
752+-- | This instance prevents from accidentally using '->' instead of ':>'
754+-- >>> serve (Proxy :: Proxy (Capture "foo" Int -> Get '[JSON] Int)) (error "...")
756+-- ...No instance HasServer (a -> b).
757+-- ...Maybe you have used '->' instead of ':>' between
758+-- ...Capture "foo" Int
760+-- ...Verb 'GET 200 '[JSON] Int
763+-- >>> undefined :: Server (Capture "foo" Int -> Get '[JSON] Int)
765+-- ...No instance HasServer (a -> b).
766+-- ...Maybe you have used '->' instead of ':>' between
767+-- ...Capture "foo" Int
769+-- ...Verb 'GET 200 '[JSON] Int
772+instance TypeError (HasServerArrowTypeError a b) => HasServer (a -> b) context
774+ type ServerT (a -> b) m = TypeError (HasServerArrowTypeError a b)
775+ route _ _ _ = error "servant-server panic: impossible happened in HasServer (a -> b)"
776+ hoistServerWithContext _ _ _ = id
778+type HasServerArrowTypeError a b =
779+ 'Text "No instance HasServer (a -> b)."
780+ ':$$: 'Text "Maybe you have used '->' instead of ':>' between "
787+-- >>> import Servant