137 lines
3.2 KiB
TeX
137 lines
3.2 KiB
TeX
\documentclass[12pt]{beamer}
|
||
\usetheme{metropolis}
|
||
\usepackage{minted}
|
||
|
||
\newenvironment{code}{\ttfamily}{\par}
|
||
|
||
\title{servant}
|
||
\subtitle{Defining web APIs at the type-level}
|
||
|
||
\begin{document}
|
||
\metroset{titleformat frame=smallcaps}
|
||
\setminted{fontsize=\scriptsize}
|
||
|
||
|
||
\maketitle
|
||
|
||
\section{Introduction}
|
||
|
||
\begin{frame}{Type-level DSLs?}
|
||
\begin{itemize}
|
||
\item (Uninhabited) types with attached ``meaning''
|
||
\item The Expression Problem (Wadler 1998)
|
||
\item API representation and interpretation are separated
|
||
\item APIs become first-class citizens
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Haskell extensions}
|
||
\begin{itemize}
|
||
\item TypeOperators
|
||
\item DataKinds
|
||
\item TypeFamilies
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{A servant example}
|
||
\begin{minted}{haskell}
|
||
type PubAPI = "pubs" :> Get ’[JSON] [Pub]
|
||
:<|> "pubs" :> "tagged"
|
||
:> Capture "tag" Text
|
||
:> Get ’[JSON] [Pub]
|
||
\end{minted}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{Computed types}
|
||
\begin{minted}{haskell}
|
||
type TaggedPubs = "tagged" :> Capture "tag" Text :> ...
|
||
|
||
taggedPubsHandler :: Server TaggedPubs
|
||
taggedPubsHandler tag = ...
|
||
\end{minted}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{Computed types}
|
||
\begin{minted}{haskell}
|
||
type TaggedPubs = "tagged" :> Capture "tag" Text :> ...
|
||
|
||
taggedPubsHandler :: Server TaggedPubs
|
||
taggedPubsHandler tag = ...
|
||
|
||
Server TaggedPubs ~
|
||
Text -> EitherT ServantErr IO [Pub]
|
||
\end{minted}
|
||
\end{frame}
|
||
|
||
\section{Interpretations}
|
||
|
||
\begin{frame}{servant-server}
|
||
The one everyone is interested in!
|
||
|
||
\begin{itemize}
|
||
\item Based on WAI, can run on warp
|
||
\item Interprets combinators with a simple \texttt{HasServer c} class
|
||
\item Easy to use!
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{HasServer ...}
|
||
\begin{minted}{haskell}
|
||
instance (KnownSymbol path, HasServer sublayout)
|
||
=> HasServer (path :> sublayout) where
|
||
type ServerT (path :> sublayout) m = ServerT sublayout m
|
||
|
||
route ...
|
||
where
|
||
pathString = symbolVal (Proxy :: Proxy path)
|
||
\end{minted}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{Server example}
|
||
\begin{minted}{haskell}
|
||
type Echo = Capture "echo" Text :> Get ’[PlainText] Text
|
||
|
||
echoAPI :: Proxy Echo
|
||
echoAPI = Proxy
|
||
|
||
echoServer :: Server Echo
|
||
echoServer = return
|
||
\end{minted}
|
||
\end{frame}
|
||
|
||
\begin{frame}{servant-client}
|
||
\begin{itemize}
|
||
\item Generates Haskell client functions for API
|
||
\item Same types as API specification: For RPC the whole ``web layer'' is abstracted away
|
||
\item Also easy to use!
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{servant-docs, servant-js ...}
|
||
Many other interpretations exist already, for example:
|
||
\begin{itemize}
|
||
\item Documentation generation
|
||
\item Foreign function export (e.g. Elm, JavaScript)
|
||
\item Mock-server generation
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\section{Demo}
|
||
|
||
\section{Conclusion}
|
||
|
||
\begin{frame}{Drawbacks}
|
||
\begin{itemize}
|
||
\item Haskell has no custom open kinds (yet)
|
||
\item Proxies are ugly
|
||
\item Errors can be a bit daunting
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Questions?}
|
||
Ølkartet: github.com/tazjin/pubkartet \\
|
||
Slides: github.com/tazjin/servant-presentation
|
||
|
||
@tazjin
|
||
\end{frame}
|
||
\end{document}
|