@@ -15,8 +15,18 @@ module Servant.Server.Internal.Config where
1515import Data.Proxy
1616import GHC.TypeLits
1717
18−-- | The entire configuration.
19−data Config a where
18+-- | When calling 'Servant.Server.serve' you have to supply a configuration
19+-- value of type @'Config' configTypes@. This parameter is used to pass values
20+-- to combinators. (It shouldn't be confused with general configuration
21+-- parameters for your web app, like the port, etc.). If you don't use
22+-- combinators that require any config entries, you can just pass 'EmptyConfig'.
23+-- To create a config with entries, use the operator @(':.')@. The parameter of
24+-- the type 'Config' is a type-level list reflecting the types of the contained
25+-- config entries:
26+--
27+-- >>> :type True :. () :. EmptyConfig
28+-- True :. () :. EmptyConfig :: Config '[Bool, ()]
29+data Config configTypes where
2030 EmptyConfig :: Config '[]
2131 (:.) :: x -> Config xs -> Config (x ': xs)
2232infixr 5 :.
@@ -33,6 +43,19 @@ instance Eq (Config '[]) where
3343instance (Eq a, Eq (Config as)) => Eq (Config (a ': as)) where
3444 x1 :. y1 == x2 :. y2 = x1 == x2 && y1 == y2
3545
46+-- | This class is used to access config entries in 'Config's. 'getConfigEntry'
47+-- returns the first value where the type matches:
48+--
49+-- >>> getConfigEntry (True :. False :. EmptyConfig) :: Bool
50+-- True
51+--
52+-- If the 'Config' does not contain an entry of the requested type, you'll get
53+-- an error:
54+--
55+-- >>> getConfigEntry (True :. False :. EmptyConfig) :: String
56+-- ...
57+-- No instance for (HasConfigEntry '[] [Char])
58+-- ...
3659class HasConfigEntry (config :: [*]) (val :: *) where
3760 getConfigEntry :: Config config -> val
3861
@@ -46,9 +69,28 @@ instance OVERLAPPING_
4669
4770-- * support for named subconfigs
4871
72+-- | Normally config entries are accessed by their types. In case you need
73+-- to have multiple values of the same type in your 'Config' and need to access
74+-- them, we provide 'NamedConfig'. You can think of it as sub-namespaces for
75+-- 'Config's.
4976data NamedConfig (name :: Symbol) (subConfig :: [*])
5077 = NamedConfig (Config subConfig)
5178
79+-- | 'descendIntoNamedConfig' allows you to access `NamedConfig's. Usually you
80+-- won't have to use it yourself but instead use a combinator like
81+-- 'Servant.API.WithNamedConfig.WithNamedConfig'.
82+--
83+-- This is how 'descendIntoNamedConfig' works:
84+--
85+-- >>> :set -XFlexibleContexts
86+-- >>> let subConfig = True :. EmptyConfig
87+-- >>> :type subConfig
88+-- subConfig :: Config '[Bool]
89+-- >>> let parentConfig = False :. (NamedConfig subConfig :: NamedConfig "subConfig" '[Bool]) :. EmptyConfig
90+-- >>> :type parentConfig
91+-- parentConfig :: Config '[Bool, NamedConfig "subConfig" '[Bool]]
92+-- >>> descendIntoNamedConfig (Proxy :: Proxy "subConfig") parentConfig :: Config '[Bool]
93+-- True :. EmptyConfig
5294descendIntoNamedConfig :: forall config name subConfig .
5395 HasConfigEntry config (NamedConfig name subConfig) =>
5496 Proxy (name :: Symbol) -> Config config -> Config subConfig