@@ -15,8 +15,18 @@ module Servant.Server.Internal.Config where
15
15
import Data.Proxy
16
16
import GHC.TypeLits
17
17
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
20
30
EmptyConfig :: Config '[]
21
31
(:.) :: x -> Config xs -> Config (x ': xs )
22
32
infixr 5 :.
@@ -33,6 +43,19 @@ instance Eq (Config '[]) where
33
43
instance (Eq a , Eq (Config as )) => Eq (Config (a ': as )) where
34
44
x1 :. y1 == x2 :. y2 = x1 == x2 && y1 == y2
35
45
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
+ -- ...
36
59
class HasConfigEntry (config :: [* ]) (val :: * ) where
37
60
getConfigEntry :: Config config -> val
38
61
@@ -46,9 +69,28 @@ instance OVERLAPPING_
46
69
47
70
-- * support for named subconfigs
48
71
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.
49
76
data NamedConfig (name :: Symbol ) (subConfig :: [* ])
50
77
= NamedConfig (Config subConfig )
51
78
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
52
94
descendIntoNamedConfig :: forall config name subConfig .
53
95
HasConfigEntry config (NamedConfig name subConfig ) =>
54
96
Proxy (name :: Symbol ) -> Config config -> Config subConfig
0 commit comments