Skip to content

Commit a19cb84

Browse files
committed
Update changelog
1 parent 9d66e16 commit a19cb84

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

Diff for: changelog.d/1556

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
synopsis: Display capture hints in router layout
2+
prs: #1556
3+
4+
description: {
5+
6+
This PR enhances the `Servant.Server.layout` function, which produces a textual description of the routing layout of an API. More precisely, it changes `<capture>` blocks, so that they display the name and type of the variable being captured instead.
7+
8+
Example:
9+
10+
For the following API
11+
```haskell
12+
type API =
13+
"a" :> "d" :> Get '[JSON] NoContent
14+
:<|> "b" :> Capture "x" Int :> Get '[JSON] Bool
15+
:<|> "a" :> "e" :> Get '[JSON] Int
16+
```
17+
18+
we previously got the following output:
19+
20+
```
21+
/
22+
├─ a/
23+
│ ├─ d/
24+
│ │ └─•
25+
│ └─ e/
26+
│ └─•
27+
└─ b/
28+
└─ <capture>/
29+
├─•
30+
31+
└─•
32+
```
33+
34+
now we get:
35+
36+
```
37+
/
38+
├─ a/
39+
│ ├─ d/
40+
│ │ └─•
41+
│ └─ e/
42+
│ └─•
43+
└─ b/
44+
└─ <x::Int>/
45+
├─•
46+
47+
└─•
48+
```
49+
50+
This change is achieved by the introduction of a CaptureHint type, which is passed as an extra argument to the CaptureRouter and CaptureAllRouter constructors for the Router' type.
51+
CaptureHint values are then used in routerLayout, to display the name and type of captured values, instead of just `<capture>` previously.
52+
53+
N.B.:
54+
Because the choice smart constructor for routers can aggregate Capture combinators with different capture hints, the Capture*Router constructors actually take a list of CaptureHint, instead of a single one.
55+
56+
This PR also introduces Spec tests for the routerLayout function.
57+
58+
Warning:
59+
This change is potentially breaking, because it adds the constraint `Typeable a` to all types that are to be captured. Because all types are typeable since GHC 7.10, this is not as bad as it sounds ; it only break expressions where `a` is quantified in an expression with `Capture a`.
60+
In those cases, the fix is easy: it suffices to add `Typeable a` to the left-hand side of the quantification constraint.
61+
62+
For instance, the following code will no longer compile:
63+
```haskell
64+
type MyAPI a = Capture "foo" a :> Get '[JSON] ()
65+
66+
myServer :: forall a. Server (MyAPI a)
67+
myServer = const $ return ()
68+
69+
myApi :: forall a. Proxy (MyAPI a)
70+
myApi = Proxy
71+
72+
app :: forall a. (FromHttpApiData a) => Application
73+
app = serve (myApi @a) (myServer @a)
74+
```
75+
76+
Indeed, `app` should be replaced with:
77+
```haskell
78+
app :: forall a. (FromHttpApiData a, Typeable a) => Application
79+
app = serve (myApi @a) (myServer @a)
80+
```
81+
}

0 commit comments

Comments
 (0)