\documentclass{beamer} \usepackage{pgfpages} \title[Thermoprint]{Thermoprint -- A Toolset for Interacting With Character Based Printers} \subtitle[]{A Project in Advanced Functional Programming} \author{Gregor Kleen} \date{WiSe 2015--16} \beamertemplatenavigationsymbolsempty \usetheme{Montpellier} \usecolortheme{dove} \setbeameroption{show notes on second screen} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage[tt=false]{libertine} \usepackage{tikz} \usetikzlibrary{positioning,shapes} \usepackage{varwidth} \newsavebox\IBox \newenvironment{resizefig}[1][\textwidth]{\gdef\figWidth{#1}\begin{lrbox}{\IBox}\varwidth{\textwidth}\centering}{\endvarwidth\end{lrbox}\resizebox{\figWidth}{!}{\usebox\IBox}} \usepackage{listings} \lstset{language=Haskell} \lstset{basicstyle=\ttfamily,breaklines=true,postbreak=\raisebox{0ex}[0ex][0ex]{\ensuremath{\color{gray}\hookrightarrow\space}}} \begin{document} \frame{\titlepage} \frame{\tableofcontents} \section{Motivation} \begin{frame} \frametitle{How to Talk to a Line Thermal Printer} \begin{description} \item[\texttt{ESC/POS}] \begin{itemize} \item An industry standard \item Control-\alert{bytes} \end{itemize} \end{description} \emph{Preparing printouts manually is ridiculous.}\\ Therefore: \alert{semantic} document format \end{frame} \section{Project Structure} \begin{frame} \begin{figure} \begin{resizefig}[0.8\textwidth] \begin{tikzpicture}[node distance=4cm] \tikzstyle{package} = [rectangle, draw=black!80] \node[package] (spec) [] {thermoprint-spec}; \node[package] (tprint) [below of=spec] {tprint}; \node[package] (client) [right of=tprint] {thermoprint-client}; \node[package] (webgui) [below of=tprint] {thermoprint-webgui}; \node[package] (tp-bbcode) [left of=tprint] {thermoprint-bbcode}; \node[package] (bbcode) [above of=tp-bbcode] {bbcode}; \node[package] (server) [right of=spec] {thermoprint-server}; \draw[->] (client) to (spec); \draw[->] (tprint) to (client); \draw[->] (webgui) to (client); \draw[->] (tprint) to (tp-bbcode); \draw[->] (webgui) to (tp-bbcode); \draw[->] (tp-bbcode) to (bbcode); \draw[->] (tp-bbcode) to (spec); \draw[->] (server) to (spec); \draw[->, dashed] (server) -- (client); \end{tikzpicture} \label{fig:cabal_dep_graph} \caption{Dependency graph} \end{resizefig} \end{figure} \note[item]{\texttt{theromprint-spec}: defines API \& document format} \note[item]{\texttt{bbcode}: parser for bbcode} \note[item]{\texttt{tp-bbcode}: parses bbcode Document Object Model to document format} \note[item]{\texttt{client}: derivation of client for API defined in \texttt{thermoprint-spec}} \note[item]{\texttt{server}: implementation of server for API defined in \texttt{thermoprint-spec} (mostly database Create Read Update \& Delete)} \note[item]{\texttt{webgui}: uses \texttt{tp-bbcode}, \texttt{client} and (a patched version of) \texttt{threepenny}} \note[item]{\texttt{tprint}: uses \texttt{tp-bbcode}, \texttt{client} and \texttt{optparse-applicative}} \note[item]{\texttt{server} uses \texttt{client} only for testing (also covers \texttt{client})} \end{frame} \section{An Introduction to Servant} \begin{frame}[fragile] \frametitle{An API} \begin{lstlisting} -- GET /date type MyAPI = "date" :> Get '[JSON] Date -- GET /time/:tz :<|> "time" :> Capture "tz" Timezone :> Get '[JSON] Time myAPI :: Proxy MyAPI myAPI = Proxy \end{lstlisting} \note[item]{\texttt{:<|>} combines two alternative apis into one (isomorphic to \texttt{(,)})} \note[item]{\texttt{:>} composes parts of url: literals (\texttt{-XOverloadedStrings}), captures, query arguments, endpoints\\also isomorphic to \texttt{(,)} -- binds stronger than \texttt{:<|>}} \note[item]{\texttt{'[JSON]} is a type of the kind \texttt{[JSON]} -- acceptable encodings carried within the type (\texttt{-XDataKinds})} \end{frame} \begin{frame}[fragile] \frametitle{A Server} \begin{lstlisting} server :: Server MyAPI server = getDate :<|> getTimeForTZ where getDate :: EitherT ServantErr IO Date getDate = liftIO getCurrentDate getTimeForTZ :: Timezone -> EitherT ServantErr IO Time getTimeForTZ = liftIO . getTimeAtTZ main :: IO () main = run 8000 $ serve myAPI server serve :: HasServer layout => Proxy layout -> Server layout -> Application \end{lstlisting} \note[item]{\texttt{Application} \& \texttt{run} from wai and warp} \note[item]{\texttt{HasServer} maps api type to handler type via associated type family \& recursion} \note[item]{servant provides utilities for changing monad -- \texttt{:<|>} is associative under (effectively) monad functors} \end{frame} \begin{frame}[fragile] \frametitle{A Client} \begin{lstlisting} getCurrentDate :: EitherT ServantError IO Date getTimeAtTZ :: Timezone -> EitherT ServantError IO Time (getCurrentDate :<|> getTimeAtTZ) = client myAPI url where url = BaseUrl Http "localhost" 8000 client :: HasClient layout => Proxy layout -> BaseUrl -> Client layout \end{lstlisting} \note[item]{\texttt{Client} is associated type family of \texttt{HasClient}} \note[item]{\texttt{:<|>} on left side of \texttt{=} is pattern match} \end{frame} \section{On the Difficulties Existentially Quantified Configuration Introduces} \begin{frame}[fragile] \frametitle{Thermoprints Use of Existential Quantification} \begin{lstlisting} type QueueManager t = StateT Queue t STM () -- Not really intersection :: [QueueManager t] -> QueueManager t idQM :: QueueManager t data QMConfig m where QMConfig :: (MonadTrans t, …) => QueueManager t -> (t IO) :~> m -> QMConfig m \end{lstlisting} \pause Can we build \texttt{intersection} and \texttt{idQM} for \texttt{QMConfig}? \note[item]<1>{\texttt{QueueManager}s manage queues.} \note[item]<1>{\texttt{QMConfig} makes configuration nicer for the user (methinks)} \note[item]<1>{\texttt{:$\sim$>} means monad functor in servant-speak} \note[item]<2>{Combining \texttt{QueueManager}s is obviously useful. Why not \texttt{QMConfig}s?} \end{frame} \begin{frame}[fragile] \frametitle{Difficulty in combining \texttt{QMConfig}s} \begin{lstlisting} combineMgrs :: Monad (t (t' IO)) => QueueManager t -> QueueManager t' -> QueueManager (ComposeT t t') combine :: {-# constraints #-} QMConfig m -> QMConfig m -> QMConfig m \end{lstlisting} \note[item]{\texttt{QMConfig} carries constraints -- we need them for the result} \note[item]{\texttt{QMConfig} carries no information about its transformer in its type} \note[item]{Therefore we cannot construct a constraint for \texttt{combine}} \note[item]{We \emph{might} be able to have \texttt{QMConfig} carry the necessary constraints for \texttt{combine} but thats difficult.\\Might be possible with quantified constraints (available on hackage), but not easily -- no partially applied types in haskell} \end{frame} \end{document}