forked from haskell-servant/haskell-servant.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrss.xml
157 lines (146 loc) · 17.3 KB
/
rss.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>haskell-servant blog</title>
<link>http://haskell-servant.github.io</link>
<description><![CDATA[Posts from the haskell-servant blog]]></description>
<atom:link href="http://haskell-servant.github.io/rss.xml" rel="self"
type="application/rss+xml" />
<lastBuildDate>Mon, 25 May 2015 00:00:00 UT</lastBuildDate>
<item>
<title>servant paper submitted to WGP 2015</title>
<link>http://haskell-servant.github.io/posts/2015-05-25-servant-paper-wgp-2015.html</link>
<description><![CDATA[<p>Sönke Hahn, Julian Arni, Andres Löh and myself have submitted a paper about <em>servant</em> to the <a href="http://www.wgp-sigplan.org/farmer/doku.php?id=2015">11th ACM SIGPLAN Workshop on Generic Programming</a>. Here’s the abstract.</p>
<blockquote>
<p>We describe the design and motivation for Servant, an extensible, type-level DSL for describing Web APIs. Servant APIs are Haskell types. An API type can be interpreted in several different ways: as a server that processes requests, interprets them and dispatches them to appropriate handlers; as a client that can correctly query the endpoints of the API; as systematic documentation for the API; and more. Servant is fully extensible: the API language can be augmented with new constructs, and new interpretations can be defined. The key Haskell features making all this possible are data kinds, (open) type families and (open) type classes. The techniques we use are reminiscent of general-purpose generic programming. However, where most generic programming libraries are interested in automatically deriving programs for a large class of datatypes from many different domains, we are only interested in a small class of datatypes that is used in the DSL for describing APIs.</p>
</blockquote>
<p>The full draft is available <a href="http://alpmestan.com/servant/servant-wgp.pdf">here</a>.</p>
<div class="info">
Posted on May 25, 2015
by Alp Mestanogullari
</div>
]]></description>
<pubDate>Mon, 25 May 2015 00:00:00 UT</pubDate>
<guid>http://haskell-servant.github.io/posts/2015-05-25-servant-paper-wgp-2015.html</guid>
<dc:creator>servant developers</dc:creator>
</item>
<item>
<title>servant 0.4 released</title>
<link>http://haskell-servant.github.io/posts/2015-05-10-servant-0.4-released.html</link>
<description><![CDATA[<div id="toc"><h3>Table of contents</h3><ul>
<li><a href="#multiple-content-type-support">Multiple content-type support</a></li>
<li><a href="#servant-blaze-and-servant-lucid"><em>servant-blaze</em> and <em>servant-lucid</em></a></li>
<li><a href="#response-headers">Response headers</a></li>
<li><a href="#running-handlers-in-other-monads-than-eithert">Running handlers in other monads than <code>EitherT</code></a></li>
<li><a href="#mklink">mkLink</a></li>
<li><a href="#left">Left</a></li>
<li><a href="#baseurl">BaseUrl</a></li>
<li><a href="#complete-changelogs">Complete CHANGELOGs</a></li>
<li><a href="#website">Website</a></li>
<li><a href="#conclusions">Conclusions</a></li>
</ul></div>
<p>Since <a href="http://alpmestan.com/posts/2014-12-09-rethinking-webservices-apis-haskell.html">the last major release</a>, a lot happened in and around <em>servant</em>. Definitely enough to justify a new release. This post announces new releases of all the servant packages, with many local changes but also some major ones that affect all packages. You can find the detailed changelogs at the end of this post, but here are a few major features you may want to learn about. This website also features a <a href="/tutorial">new tutorial</a> that explains how to use <em>servant</em> from scratch.</p>
<section id="multiple-content-type-support" class="level1">
<h1>Multiple content-type support</h1>
<p><em>servant</em> combinators are not JSON-centric anymore.</p>
<p>If you had an API type like the following with servant <em>0.2.x</em>:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">API</span> <span class="fu">=</span> <span class="co">-- list users</span>
<span class="st">"users"</span> <span class="fu">:></span> <span class="dt">Get</span> [<span class="dt">User</span>]
<span class="co">-- update an user</span>
<span class="fu">:<|></span> <span class="st">"user"</span> <span class="fu">:></span> <span class="dt">Capture</span> <span class="st">"username"</span> <span class="dt">Text</span> <span class="fu">:></span> <span class="dt">ReqBody</span> <span class="dt">User</span> <span class="fu">:></span> <span class="dt">Put</span> ()</code></pre>
<p>You now have to change it to:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">API</span> <span class="fu">=</span> <span class="co">-- list users</span>
<span class="st">"users"</span> <span class="fu">:></span> <span class="dt">Get</span> <span class="ch">'[JSON] [User]</span>
<span class="fu">:<|></span> <span class="st">"user"</span> <span class="fu">:></span> <span class="dt">Capture</span> <span class="st">"username"</span> <span class="dt">Text</span> <span class="fu">:></span> <span class="dt">ReqBody</span> <span class="ch">'[JSON] User :> Put '</span>[<span class="dt">JSON</span>] ()</code></pre>
<p>Wherever applicable (i.e <code>ReqBody</code> and all the combinators that correspond to an HTTP method), you can now specify all the content types in which you want to want to be able to encode/decode values. As you can see, we use the <code>DataKinds</code> GHC extension to let you specify a type-level list of content-types, which are simple dummy types:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">JSON</span></code></pre>
<p>In <em>servant-server</em>, a list of these content-types as the first argument of a method gets translated into a set of constraints on the return type:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="dt">Get</span> <span class="ch">'[JSON, PlainText] Int</span>
<span class="fu">==></span>
<span class="dt">MimeRender</span> <span class="dt">JSON</span> <span class="dt">Int</span>, <span class="dt">MimeRender</span> <span class="dt">PlainText</span> <span class="dt">Int</span> <span class="ot">=></span> <span class="dt">EitherT</span> <span class="dt">ServantErr</span> <span class="dt">IO</span> <span class="dt">Int</span></code></pre>
<p>Which have unsurprising instances:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">instance</span> (<span class="dt">ToJSON</span> a) <span class="ot">=></span> <span class="dt">MimeRender</span> <span class="dt">JSON</span> a</code></pre>
<p>Thus, <em>servant</em> checks at <em>compile-time</em> that it really can serialize your values as you describe. And of course, it handles picking the appropriate serialization format based on the request’s “Accept” header for you.</p>
<p>(For <code>ReqBody</code>, <em>deserialization</em> is involved. For <em>servant-client</em>, the logic goes the other way around - serialization for <code>ReqBody</code>, deserialization for methods.)</p>
</section>
<section id="servant-blaze-and-servant-lucid" class="level1">
<h1><em>servant-blaze</em> and <em>servant-lucid</em></h1>
<p>Declaring new content-types, and the associated constraints for them, is quite easy. But to make it easier still, we are also announcing two new packages: servant-blaze and servant-lucid. To use them, just import their <code>HTML</code> datatype:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">import </span><span class="dt">Servant.HTML.Lucid</span> (<span class="dt">HTML</span>) <span class="co">-- or Servant.HTML.Blaze</span>
<span class="kw">type</span> <span class="dt">MyHTML</span> <span class="fu">=</span> <span class="dt">Get</span> <span class="ch">'[HTML] User</span></code></pre>
<p>And <code>User</code> will be checked for the appropriate (e.g. <code>ToHtml</code>) instance.</p>
</section>
<section id="response-headers" class="level1">
<h1>Response headers</h1>
<p>There was no easy way so far to have handlers add headers to a response. We’ve since come up with a solution that stays true to the <em>servant</em> spirit: <em>what</em> headers your response will include (and what their types are) is still enforced statically:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">MyHandler</span> <span class="fu">=</span> <span class="dt">Get</span> <span class="ch">'[JSON] (Headers '</span>[<span class="dt">Header</span> <span class="st">"Location"</span> <span class="dt">Link</span>] <span class="dt">User</span>)
<span class="ot">myHandler ::</span> <span class="dt">Server</span> <span class="dt">MyHandler</span>
myHandler <span class="fu">=</span> return <span class="fu">$</span> addHeader <span class="fu"><</span>someLink<span class="fu">></span> <span class="fu">$</span> <span class="fu"><</span>someuser<span class="fu">></span></code></pre>
<p><em>servant-docs</em> and <em>servant-client</em> are also response-header aware.</p>
<p>Our current solution isn’t something we are entirely happy with from an internal persepctive. We use overlapping instances for all the handlers, which some might think is already a problem. But more concretely, there’s the threat of an exponential blowup in the number of instances we have to declare. And that can be a problem for end users too, if they decide to further modify behavior via a similar mechanism. But these things thankfully don’t seem to pose any <em>immediate</em> problems.</p>
</section>
<section id="running-handlers-in-other-monads-than-eithert" class="level1">
<h1>Running handlers in other monads than <code>EitherT</code></h1>
<p>An often-requested feature has been easy use of datatypes/monads besides <code>EitherT</code>. Now we believe we have a good story for that (thanks in large part to <a href="http://github.com/rschatz">rschatz</a>). To convert from one datatype to another, all you need to do is provide a natural transformation between them. For example:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">ReaderAPI</span> <span class="fu">=</span> <span class="st">"a"</span> <span class="fu">:></span> <span class="dt">Get</span> <span class="ch">'[JSON] Int</span>
<span class="fu">:<|></span> <span class="st">"b"</span> <span class="fu">:></span> <span class="dt">Get</span> <span class="ch">'[JSON] String</span>
<span class="ot">readerServerT ::</span> <span class="dt">ServerT</span> <span class="dt">ReaderAPI</span> (<span class="dt">Reader</span> <span class="dt">String</span>)
readerServerT <span class="fu">=</span> return <span class="dv">1797</span> <span class="fu">:<|></span> ask
<span class="ot">readerServer ::</span> <span class="dt">Server</span> <span class="dt">ReaderAPI</span>
readerServer <span class="fu">=</span> enter (<span class="dt">Nat</span> <span class="fu">$</span> return <span class="fu">.</span> (<span class="ot">`runReader`</span> <span class="st">"hi"</span>)) readerServerT</code></pre>
<p>The new <code>ServerT</code> type synonym takes an extra paramer that represents what datatype/monad you are using over your handlers (instead of <code>EitherT ServantErr IO</code>).</p>
<p>(Note that we also provide a number of pre-existing <code>Nat</code>s, which are an instance of <code>Category</code>. We could have used</p>
<pre><code>readerServer = enter (generalizeNat . (runReaderTNat "hi")) readerServerT</code></pre>
<p>instead (with <code>.</code> being from <code>Control.Category</code>).)</p>
<p>Note that the datatypes you can use now don’t even need to be monads!</p>
</section>
<section id="mklink" class="level1">
<h1>mkLink</h1>
<p>Somewhere between the 0.2 release and now, <code>mkLink</code> got a whole lot better (thanks Christian Marie!). <code>mkLink</code> makes urls that are statically guaranteed to belong to your API, without any Template Haskell. Combined with response headers, you can now easily create, for instance, type-safe redirect headers. Combined with the new HTML support, you can easily make links that you know will not 404.</p>
</section>
<section id="left" class="level1">
<h1>Left</h1>
<p>We also changed the default type of handlers from <code>EitherT (Int,String) IO a</code> to <code>EitherT ServantErr IO a</code>. Now it is possible to return headers and a response body in the <code>Left</code> case.</p>
<p>We also now export function <code>errXXX</code> (where <code>XXX</code> is a 300-599 HTTP status code) with sensible reason strings.</p>
</section>
<section id="baseurl" class="level1">
<h1>BaseUrl</h1>
<p>We also changed the <code>client</code> function from <code>servant-client</code> so that, instead of returning various functions that each take a <code>BaseUrl</code> argument (often in inconvenient argument positions), the <code>client</code> function itself takes a <code>BaseUrl</code> argument, and the functions it returns don’t. So the type of <code>client</code> went from</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">client ::</span> <span class="dt">HasClient</span> (<span class="dt">Canonicalize</span> layout) <span class="ot">=></span> <span class="dt">Proxy</span> layout <span class="ot">-></span> <span class="dt">Client</span> layout</code></pre>
<p>To</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">client ::</span> <span class="dt">HasClient</span> (<span class="dt">Canonicalize</span> layout) <span class="ot">=></span> <span class="dt">Proxy</span> layout <span class="ot">-></span> <span class="dt">BaseUrl</span> <span class="ot">-></span> <span class="dt">Client</span> layout</code></pre>
</section>
<section id="complete-changelogs" class="level1">
<h1>Complete CHANGELOGs</h1>
<ul>
<li><a href="http://hackage.haskell.org/package/servant-0.4.0/changelog">servant</a></li>
<li><a href="http://hackage.haskell.org/package/servant-server-0.4.0/changelog">servant-server</a></li>
<li><a href="http://hackage.haskell.org/package/servant-client-0.4.0/changelog">servant-client</a></li>
<li><a href="http://hackage.haskell.org/package/servant-docs-0.4.0/changelog">servant-docs</a></li>
<li><a href="http://hackage.haskell.org/package/servant-jquery-0.4.0/changelog">servant-jquery</a></li>
</ul>
</section>
<section id="website" class="level1">
<h1>Website</h1>
<p>We also decided to switch to hakyll in order to be able to have a blog as well as some static pages that collect tips and tricks that people have found. We also used this opportunity to rewrite the getting started into a more informative tutorial, now available <a href="/tutorial">here</a>.</p>
</section>
<section id="conclusions" class="level1">
<h1>Conclusions</h1>
<p>As you can see, more and more information is getting encoded statically - the types are becoming a pretty rich DSL. In order to keep the noise down, do what you normally do: abstract away common patterns! If your endpoints always return the same content-types, make aliases:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">Get'</span> a <span class="fu">=</span> <span class="dt">Get</span> <span class="ch">'[JSON, HTML, PlainText] a</span></code></pre>
<p>There’s still an outstanding issue with the errors servant returns when a request doesn’t get handled. For example, if the path of a request, but not the method nor the request body, match, rather than returning a 405 (Method Not Allowed) we return a 400 (Bad Request), which is not the desired behavior. Andres Löh made some great suggestions for how to improve our routing time complexity, and hopefully we can integrate a fix for this issue when we tackle that.</p>
<p>We also merged our repos into <a href="https://github.com/haskell-servant/servant">servant</a>. Please use that repo exclusively for PRs and issues (we’ll get rid of the others eventually).</p>
<p>Special thanks to <a href="https://github.com/anchor">the Anchor team</a> from Australia, <a href="https://github.com/mpickering">Matthew Pickering</a>, <a href="https://github.com/dlarsson">Daniel Larsson</a>, <a href="https://github.com/paf31">Phil Freeman</a>, <a href="https://github.com/fisx">Matthias Fischmann</a>, <a href="https://github.com/rschatz">rschatz</a>, <a href="https://github.com/Fuuzetsu">Mateusz Kowalczyk</a>, <a href="https://github.com/codedmart">Brandon Martin</a> and <a href="https://github.com/spl">Sean Leather</a> who’ve contributed from little fixes to whole new features. Several companies are now running <em>servant</em>-powered web applications.</p>
</section>
<div class="info">
Posted on May 10, 2015
by The servant team
</div>
]]></description>
<pubDate>Sun, 10 May 2015 00:00:00 UT</pubDate>
<guid>http://haskell-servant.github.io/posts/2015-05-10-servant-0.4-released.html</guid>
<dc:creator>servant developers</dc:creator>
</item>
</channel>
</rss>