diff options
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | shell.nix | 2 | ||||
| -rw-r--r-- | ws2015/ffp/presentation/presentation.pdf.gup | 8 | ||||
| -rw-r--r-- | ws2015/ffp/presentation/presentation.tex | 189 | ||||
| -rw-r--r-- | ws2015/ffp/presentation/shell.nix | 36 | ||||
| m--------- | ws2015/ffp/presentation/thermoprint.git | 0 |
6 files changed, 237 insertions, 1 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a292d0f --- /dev/null +++ b/.gitmodules | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | [submodule "ws2015/ffp/presentation/thermoprint.git"] | ||
| 2 | path = ws2015/ffp/presentation/thermoprint.git | ||
| 3 | url = git:thermoprint | ||
| @@ -14,7 +14,7 @@ pkgs.stdenv.mkDerivation rec { | |||
| 14 | with p; [ yesod yesod-bin pandoc monad-par persistent-sqlite | 14 | with p; [ yesod yesod-bin pandoc monad-par persistent-sqlite |
| 15 | ])) | 15 | ])) |
| 16 | (pkgs.texlive.combine { | 16 | (pkgs.texlive.combine { |
| 17 | inherit (pkgs.texlive) scheme-small libertine tipa cm-super context bussproofs mweights fontaxes backnaur enumitem; | 17 | inherit (pkgs.texlive) scheme-small libertine tipa cm-super context bussproofs mweights fontaxes backnaur enumitem varwidth beamer; |
| 18 | }) | 18 | }) |
| 19 | ]; | 19 | ]; |
| 20 | shellHook = '' | 20 | shellHook = '' |
diff --git a/ws2015/ffp/presentation/presentation.pdf.gup b/ws2015/ffp/presentation/presentation.pdf.gup new file mode 100644 index 0000000..b609189 --- /dev/null +++ b/ws2015/ffp/presentation/presentation.pdf.gup | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #!/usr/bin/env zsh | ||
| 2 | |||
| 3 | gup -u ${2%.pdf}.tex | ||
| 4 | |||
| 5 | for i in $(seq 0 1); do | ||
| 6 | lualatex ${2%.pdf}.tex | ||
| 7 | done | ||
| 8 | [[ -e "$2" ]] && touch "$2" | ||
diff --git a/ws2015/ffp/presentation/presentation.tex b/ws2015/ffp/presentation/presentation.tex new file mode 100644 index 0000000..7370361 --- /dev/null +++ b/ws2015/ffp/presentation/presentation.tex | |||
| @@ -0,0 +1,189 @@ | |||
| 1 | \documentclass{beamer} | ||
| 2 | \usepackage{pgfpages} | ||
| 3 | |||
| 4 | \title[Thermoprint]{Thermoprint -- A Toolset for Interacting With Character Based Printers} | ||
| 5 | \subtitle[]{A project in advanced functional programming} | ||
| 6 | \author{Gregor Kleen} | ||
| 7 | \date{WiSe 2015--16} | ||
| 8 | |||
| 9 | \beamertemplatenavigationsymbolsempty | ||
| 10 | \usetheme{Montpellier} | ||
| 11 | \usecolortheme{dove} | ||
| 12 | |||
| 13 | \setbeameroption{show notes on second screen} | ||
| 14 | |||
| 15 | \usepackage[utf8]{inputenc} | ||
| 16 | \usepackage[T1]{fontenc} | ||
| 17 | \usepackage[tt=false]{libertine} | ||
| 18 | |||
| 19 | \usepackage{tikz} | ||
| 20 | \usetikzlibrary{positioning,shapes} | ||
| 21 | |||
| 22 | \usepackage{varwidth} | ||
| 23 | \newsavebox\IBox | ||
| 24 | \newenvironment{resizefig}[1][\textwidth]{\gdef\figWidth{#1}\begin{lrbox}{\IBox}\varwidth{\textwidth}\centering}{\endvarwidth\end{lrbox}\resizebox{\figWidth}{!}{\usebox\IBox}} | ||
| 25 | |||
| 26 | \usepackage{listings} | ||
| 27 | \lstset{language=Haskell} | ||
| 28 | \lstset{basicstyle=\ttfamily,breaklines=true,postbreak=\raisebox{0ex}[0ex][0ex]{\ensuremath{\color{gray}\hookrightarrow\space}}} | ||
| 29 | |||
| 30 | \begin{document} | ||
| 31 | \frame{\titlepage} | ||
| 32 | \frame{\tableofcontents} | ||
| 33 | |||
| 34 | \section{Motivation} | ||
| 35 | |||
| 36 | \begin{frame} | ||
| 37 | \frametitle{How to Talk to a Line Thermal Printer} | ||
| 38 | \begin{description} | ||
| 39 | \item[\texttt{ESC/POS}] | ||
| 40 | \begin{itemize} | ||
| 41 | \item An industry standard | ||
| 42 | \item Control-\alert{bytes} | ||
| 43 | \end{itemize} | ||
| 44 | \end{description} | ||
| 45 | \emph{Preparing printouts manually is ridiculous.}\\ | ||
| 46 | Therefore: \alert{semantic} document format | ||
| 47 | \end{frame} | ||
| 48 | |||
| 49 | \section{Project Structure} | ||
| 50 | |||
| 51 | \begin{frame} | ||
| 52 | \begin{figure} | ||
| 53 | \begin{resizefig}[0.8\textwidth] | ||
| 54 | \begin{tikzpicture}[node distance=4cm] | ||
| 55 | \tikzstyle{package} = [rectangle, draw=black!80] | ||
| 56 | \node[package] (spec) [] {thermoprint-spec}; | ||
| 57 | \node[package] (tprint) [below of=spec] {tprint}; | ||
| 58 | \node[package] (client) [right of=tprint] {thermoprint-client}; | ||
| 59 | \node[package] (webgui) [below of=tprint] {thermoprint-webgui}; | ||
| 60 | \node[package] (tp-bbcode) [left of=tprint] {thermoprint-bbcode}; | ||
| 61 | \node[package] (bbcode) [above of=tp-bbcode] {bbcode}; | ||
| 62 | \node[package] (server) [right of=spec] {thermoprint-server}; | ||
| 63 | \draw[->] (client) to (spec); | ||
| 64 | \draw[->] (tprint) to (client); | ||
| 65 | \draw[->] (webgui) to (client); | ||
| 66 | \draw[->] (tprint) to (tp-bbcode); | ||
| 67 | \draw[->] (webgui) to (tp-bbcode); | ||
| 68 | \draw[->] (tp-bbcode) to (bbcode); | ||
| 69 | \draw[->] (tp-bbcode) to (spec); | ||
| 70 | \draw[->] (server) to (spec); | ||
| 71 | \draw[->, dashed] (server) -- (client); | ||
| 72 | \end{tikzpicture} | ||
| 73 | \label{fig:cabal_dep_graph} | ||
| 74 | \caption{Dependency graph} | ||
| 75 | \end{resizefig} | ||
| 76 | \end{figure} | ||
| 77 | |||
| 78 | \note[item]{\texttt{theromprint-spec}: defines API \& document format} | ||
| 79 | \note[item]{\texttt{bbcode}: parser for bbcode} | ||
| 80 | \note[item]{\texttt{tp-bbcode}: parses bbcode Document Object Model to document format} | ||
| 81 | \note[item]{\texttt{client}: derivation of client for API defined in \texttt{thermoprint-spec}} | ||
| 82 | \note[item]{\texttt{server}: implementation of server for API defined in \texttt{thermoprint-spec} (mostly database Create Read Update \& Delete)} | ||
| 83 | \note[item]{\texttt{webgui}: uses \texttt{tp-bbcode}, \texttt{client} and (a patched version of) \texttt{threepenny}} | ||
| 84 | \note[item]{\texttt{tprint}: uses \texttt{tp-bbcode}, \texttt{client} and \texttt{optparse-applicative}} | ||
| 85 | \note[item]{\texttt{server} uses \texttt{client} only for testing (also covers \texttt{client})} | ||
| 86 | \end{frame} | ||
| 87 | |||
| 88 | \section{An Introduction to Servant} | ||
| 89 | |||
| 90 | \begin{frame}[fragile] | ||
| 91 | \frametitle{An API} | ||
| 92 | \begin{lstlisting} | ||
| 93 | -- GET /date | ||
| 94 | type MyAPI = "date" :> Get '[JSON] Date | ||
| 95 | -- GET /time/:tz | ||
| 96 | :<|> "time" | ||
| 97 | :> Capture "tz" Timezone | ||
| 98 | :> Get '[JSON] Time | ||
| 99 | |||
| 100 | myAPI :: Proxy MyAPI | ||
| 101 | myAPI = Proxy | ||
| 102 | \end{lstlisting} | ||
| 103 | |||
| 104 | \note[item]{\texttt{:<|>} combines two alternative apis into one (isomorphic to \texttt{(,)})} | ||
| 105 | \note[item]{\texttt{:>} composes parts of url: literals (\texttt{-XOverloadedStrings}), captures, query arguments, endpoints\\also isomorphic to \texttt{(,)} -- binds stronger than \texttt{:<|>}} | ||
| 106 | \note[item]{\texttt{'[JSON]} is a type of the kind \texttt{[JSON]} -- acceptable encodings carried within the type (\texttt{-XDataKinds})} | ||
| 107 | \end{frame} | ||
| 108 | |||
| 109 | \begin{frame}[fragile] | ||
| 110 | \frametitle{A Server} | ||
| 111 | \begin{lstlisting} | ||
| 112 | server :: Server MyAPI | ||
| 113 | server = getDate :<|> getTimeForTZ | ||
| 114 | where | ||
| 115 | getDate :: EitherT ServantErr IO Date | ||
| 116 | getDate = liftIO getCurrentDate | ||
| 117 | getTimeForTZ :: Timezone | ||
| 118 | -> EitherT ServantErr IO Time | ||
| 119 | getTimeForTZ = liftIO . getTimeAtTZ | ||
| 120 | |||
| 121 | main :: IO () | ||
| 122 | main = run 8000 $ serve myAPI server | ||
| 123 | |||
| 124 | serve :: HasServer layout => Proxy layout -> Server layout -> Application | ||
| 125 | \end{lstlisting} | ||
| 126 | |||
| 127 | \note[item]{\texttt{Application} \& \texttt{run} from wai and warp} | ||
| 128 | \note[item]{\texttt{HasServer} maps api type to handler type via associated type family \& recursion} | ||
| 129 | \note[item]{servant provides utilities for changing monad -- \texttt{:<|>} is associative under (effectively) monad functors} | ||
| 130 | \end{frame} | ||
| 131 | |||
| 132 | \begin{frame}[fragile] | ||
| 133 | \frametitle{A Client} | ||
| 134 | \begin{lstlisting} | ||
| 135 | getCurrentDate :: EitherT ServantError IO Date | ||
| 136 | getTimeAtTZ :: Timezone | ||
| 137 | -> EitherT ServantError IO Time | ||
| 138 | (getCurrentDate :<|> getTimeAtTZ) = client myAPI url | ||
| 139 | where url = BaseUrl Http "localhost" 8000 | ||
| 140 | |||
| 141 | client :: HasClient layout | ||
| 142 | => Proxy layout | ||
| 143 | -> BaseUrl | ||
| 144 | -> Client layout | ||
| 145 | \end{lstlisting} | ||
| 146 | |||
| 147 | \note[item]{\texttt{Client} is associated type family of \texttt{HasClient}} | ||
| 148 | \note[item]{\texttt{:<|>} on left side of \texttt{=} is pattern match} | ||
| 149 | \end{frame} | ||
| 150 | |||
| 151 | \section{On the Difficulties Existentially Quantified Configuration Introduces} | ||
| 152 | |||
| 153 | \begin{frame}[fragile] | ||
| 154 | \frametitle{Thermoprints Use of Existential Quantification} | ||
| 155 | \begin{lstlisting} | ||
| 156 | type QueueManager t = StateT Queue t STM () | ||
| 157 | -- Not really | ||
| 158 | |||
| 159 | intersection :: [QueueManager t] -> QueueManager t | ||
| 160 | idQM :: QueueManager t | ||
| 161 | |||
| 162 | data QMConfig m where | ||
| 163 | QMConfig :: (MonadTrans t, …) => QueueManager t -> (t IO) :~> m -> QMConfig m | ||
| 164 | \end{lstlisting} | ||
| 165 | |||
| 166 | \pause | ||
| 167 | Can we build \texttt{intersection} and \texttt{idQM} for \texttt{QMConfig}? | ||
| 168 | |||
| 169 | \note[item]<1>{\texttt{QueueManager}s manage queues.} | ||
| 170 | \note[item]<1>{\texttt{QMConfig} makes configuration nicer for the user (methinks)} | ||
| 171 | \note[item]<1>{\texttt{:$\sim$>} means monad functor in servant-speak} | ||
| 172 | |||
| 173 | \note[item]<2>{Combining \texttt{QueueManager}s is obviously useful. Why not \texttt{QMConfig}s?} | ||
| 174 | \end{frame} | ||
| 175 | |||
| 176 | \begin{frame}[fragile] | ||
| 177 | \frametitle{Difficulty in combining \texttt{QMConfig}s} | ||
| 178 | \begin{lstlisting} | ||
| 179 | combineMgrs :: Monad (t (t' IO)) => QueueManager t -> QueueManager t' -> QueueManager (ComposeT t t') | ||
| 180 | |||
| 181 | combine :: {-# constraints #-} QMConfig m -> QMConfig m -> QMConfig m | ||
| 182 | \end{lstlisting} | ||
| 183 | \note[item]{\texttt{QMConfig} carries constraints -- we need them for the result} | ||
| 184 | \note[item]{\texttt{QMConfig} carries no information about its transformer in its type} | ||
| 185 | \note[item]{Therefore we cannot construct a constraint for \texttt{combine}} | ||
| 186 | \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} | ||
| 187 | \end{frame} | ||
| 188 | |||
| 189 | \end{document} | ||
diff --git a/ws2015/ffp/presentation/shell.nix b/ws2015/ffp/presentation/shell.nix new file mode 100644 index 0000000..283ab0e --- /dev/null +++ b/ws2015/ffp/presentation/shell.nix | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | { pkgs ? (import <nixpkgs> {}) | ||
| 2 | , haskellPackages ? (import ./thermoprint.git/default.nix {}).haskellPackages | ||
| 3 | }: | ||
| 4 | |||
| 5 | let | ||
| 6 | thermoprintPackages = builtins.attrValues (import ./thermoprint.git/default.nix {}); | ||
| 7 | ghc = haskellPackages.ghcWithPackages | ||
| 8 | (ps: thermoprintPackages ++ utilities ps ++ testDeps ps); | ||
| 9 | utilities = (ps: with ps; [ ]); | ||
| 10 | testDeps = (ps: with ps; [ ]); | ||
| 11 | shell = pkgs.stdenv.mkDerivation { | ||
| 12 | name = "shell"; | ||
| 13 | src = builtins.toFile "shell.sh" '' | ||
| 14 | #!/usr/bin/env zsh | ||
| 15 | |||
| 16 | typeset -a args | ||
| 17 | args=($@) | ||
| 18 | [[ $#@ -eq 0 ]] && args=("-e" "tmux") | ||
| 19 | |||
| 20 | exec urxvtc -bg white -fg black -fn "xft:DejaVu Sans Mono:pixelsize=20" $args | ||
| 21 | ''; | ||
| 22 | phases = ["installPhase"]; | ||
| 23 | installPhase = '' | ||
| 24 | mkdir -p $out/bin | ||
| 25 | install -m 555 $src $out/bin/shell | ||
| 26 | ''; | ||
| 27 | }; | ||
| 28 | in | ||
| 29 | pkgs.stdenv.mkDerivation rec { | ||
| 30 | name = "presentation-env"; | ||
| 31 | buildInputs = [ shell ghc ] ++ (with pkgs; [ pdfpc screen-message ]); | ||
| 32 | shellHook = '' | ||
| 33 | eval $(egrep ^export ${ghc}/bin/ghc) | ||
| 34 | export PROMPT_INFO="${name}" | ||
| 35 | ''; | ||
| 36 | } | ||
diff --git a/ws2015/ffp/presentation/thermoprint.git b/ws2015/ffp/presentation/thermoprint.git new file mode 160000 | |||
| Subproject 5f433ad64700907de155ed1e5155193f28f9357 | |||
