mirror of
https://github.com/sdiehl/wiwinwlh.git
synced 2024-08-16 23:40:41 +03:00
reform pdf output & mmorph
This commit is contained in:
parent
2b136ee576
commit
d364c9021c
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ includes
|
||||
*.epub
|
||||
*.agdai
|
||||
.stack-work
|
||||
tutorial.pdf
|
||||
|
3
Makefile
3
Makefile
@ -2,6 +2,7 @@ PANDOC = pandoc
|
||||
IFORMAT = markdown
|
||||
FLAGS = --standalone --toc --toc-depth=2 --highlight-style pygments
|
||||
TEMPLATE = resources/page.tmpl
|
||||
LTEMPLATE = resources/page.latex
|
||||
STYLE = css/style.css
|
||||
|
||||
HTML = tutorial.html
|
||||
@ -27,7 +28,7 @@ includes: includes.hs
|
||||
./includes < $< | $(PANDOC) -f $(IFORMAT) -t epub $(FLAGS) -o $@
|
||||
|
||||
%.pdf: %.md includes
|
||||
./includes < $< | $(PANDOC) -c -s -f $(IFORMAT) --latex-engine=xelatex $(FLAGS) -o $@
|
||||
./includes < $< | $(PANDOC) -c -s -f $(IFORMAT) --template $(LTEMPLATE) --latex-engine=xelatex $(FLAGS) -o $@
|
||||
|
||||
clean:
|
||||
-rm $(CHAPTERS) $(HTML)
|
||||
|
@ -12,7 +12,7 @@ Real Online:
|
||||
* [**HTML**](http://dev.stephendiehl.com/hask/)
|
||||
* [**Example Code**](https://github.com/sdiehl/wiwinwlh/tree/master/src)
|
||||
|
||||
Examples:
|
||||
Chapter Code Examples:
|
||||
|
||||
* [01-basics/ ](https://github.com/sdiehl/wiwinwlh/tree/master/src/01-basics/)
|
||||
* [02-monads/ ](https://github.com/sdiehl/wiwinwlh/tree/master/src/02-monads/)
|
||||
|
270
resources/page.latex
Normal file
270
resources/page.latex
Normal file
@ -0,0 +1,270 @@
|
||||
\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}
|
||||
$if(fontfamily)$
|
||||
\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}
|
||||
$else$
|
||||
\usepackage{lmodern}
|
||||
$endif$
|
||||
$if(linestretch)$
|
||||
\usepackage{setspace}
|
||||
\setstretch{$linestretch$}
|
||||
$endif$
|
||||
\usepackage{amssymb,amsmath}
|
||||
\usepackage{ifxetex,ifluatex}
|
||||
\usepackage{fixltx2e} % provides \textsubscript
|
||||
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
|
||||
\usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
$if(euro)$
|
||||
\usepackage{eurosym}
|
||||
$endif$
|
||||
\else % if luatex or xelatex
|
||||
\ifxetex
|
||||
\usepackage{mathspec}
|
||||
\else
|
||||
\usepackage{fontspec}
|
||||
\fi
|
||||
\defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}
|
||||
$if(euro)$
|
||||
\newcommand{\euro}{€}
|
||||
$endif$
|
||||
$if(mainfont)$
|
||||
\setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$}
|
||||
$endif$
|
||||
$if(sansfont)$
|
||||
\setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$]{$sansfont$}
|
||||
$endif$
|
||||
$if(monofont)$
|
||||
\setmonofont[Mapping=tex-ansi$if(monofontoptions)$,$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$endif$]{$monofont$}
|
||||
$endif$
|
||||
$if(mathfont)$
|
||||
\setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}
|
||||
$endif$
|
||||
$if(CJKmainfont)$
|
||||
\usepackage{xeCJK}
|
||||
\setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}
|
||||
$endif$
|
||||
\fi
|
||||
% use upquote if available, for straight quotes in verbatim environments
|
||||
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
|
||||
% use microtype if available
|
||||
\IfFileExists{microtype.sty}{%
|
||||
\usepackage{microtype}
|
||||
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
|
||||
}{}
|
||||
$if(geometry)$
|
||||
\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry}
|
||||
$endif$
|
||||
\usepackage{hyperref}
|
||||
$if(colorlinks)$
|
||||
\PassOptionsToPackage{usenames,dvipsnames}{color} % color is loaded by hyperref
|
||||
$endif$
|
||||
\hypersetup{unicode=true,
|
||||
$if(title-meta)$
|
||||
pdftitle={$title-meta$},
|
||||
$endif$
|
||||
$if(author-meta)$
|
||||
pdfauthor={$author-meta$},
|
||||
$endif$
|
||||
$if(keywords)$
|
||||
pdfkeywords={$for(keywords)$$keywords$$sep$; $endfor$},
|
||||
$endif$
|
||||
$if(colorlinks)$
|
||||
colorlinks=true,
|
||||
linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$,
|
||||
citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$,
|
||||
urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$,
|
||||
$else$
|
||||
pdfborder={0 0 0},
|
||||
$endif$
|
||||
breaklinks=true}
|
||||
\urlstyle{same} % don't use monospace font for urls
|
||||
$if(lang)$
|
||||
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
|
||||
\usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel}
|
||||
$if(babel-newcommands)$
|
||||
$babel-newcommands$
|
||||
$endif$
|
||||
\else
|
||||
\usepackage{polyglossia}
|
||||
\setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$}
|
||||
$for(polyglossia-otherlangs)$
|
||||
\setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$}
|
||||
$endfor$
|
||||
\fi
|
||||
$endif$
|
||||
$if(natbib)$
|
||||
\usepackage{natbib}
|
||||
\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}
|
||||
$endif$
|
||||
$if(biblatex)$
|
||||
\usepackage$if(biblio-style)$[style=$biblio-style$]$endif${biblatex}
|
||||
$if(biblatexoptions)$\ExecuteBibliographyOptions{$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$}$endif$
|
||||
$for(bibliography)$
|
||||
\addbibresource{$bibliography$}
|
||||
$endfor$
|
||||
$endif$
|
||||
$if(listings)$
|
||||
\usepackage{listings}
|
||||
$endif$
|
||||
$if(lhs)$
|
||||
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
|
||||
$endif$
|
||||
$if(highlighting-macros)$
|
||||
$highlighting-macros$
|
||||
$endif$
|
||||
$if(verbatim-in-note)$
|
||||
\usepackage{fancyvrb}
|
||||
\VerbatimFootnotes % allows verbatim text in footnotes
|
||||
$endif$
|
||||
$if(tables)$
|
||||
\usepackage{longtable,booktabs}
|
||||
$endif$
|
||||
$if(graphics)$
|
||||
\usepackage{graphicx,grffile}
|
||||
\makeatletter
|
||||
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
|
||||
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
|
||||
\makeatother
|
||||
% Scale images if necessary, so that they will not overflow the page
|
||||
% margins by default, and it is still possible to overwrite the defaults
|
||||
% using explicit options in \includegraphics[width, height, ...]{}
|
||||
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
|
||||
$endif$
|
||||
$if(links-as-notes)$
|
||||
% Make links footnotes instead of hotlinks:
|
||||
\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
|
||||
$endif$
|
||||
$if(strikeout)$
|
||||
\usepackage[normalem]{ulem}
|
||||
% avoid problems with \sout in headers with hyperref:
|
||||
\pdfstringdefDisableCommands{\renewcommand{\sout}{}}
|
||||
$endif$
|
||||
$if(indent)$
|
||||
$else$
|
||||
\IfFileExists{parskip.sty}{%
|
||||
\usepackage{parskip}
|
||||
}{% else
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{6pt plus 2pt minus 1pt}
|
||||
}
|
||||
$endif$
|
||||
\setlength{\emergencystretch}{3em} % prevent overfull lines
|
||||
\providecommand{\tightlist}{%
|
||||
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
$if(numbersections)$
|
||||
\setcounter{secnumdepth}{5}
|
||||
$else$
|
||||
\setcounter{secnumdepth}{0}
|
||||
$endif$
|
||||
$if(subparagraph)$
|
||||
$else$
|
||||
% Redefines (sub)paragraphs to behave more like sections
|
||||
\ifx\paragraph\undefined\else
|
||||
\let\oldparagraph\paragraph
|
||||
\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}
|
||||
\fi
|
||||
\ifx\subparagraph\undefined\else
|
||||
\let\oldsubparagraph\subparagraph
|
||||
\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}
|
||||
\fi
|
||||
$endif$
|
||||
$if(dir)$
|
||||
\ifxetex
|
||||
% load bidi as late as possible as it modifies e.g. graphicx
|
||||
$if(latex-dir-rtl)$
|
||||
\usepackage[RTLdocument]{bidi}
|
||||
$else$
|
||||
\usepackage{bidi}
|
||||
$endif$
|
||||
\fi
|
||||
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
|
||||
\TeXXeTstate=1
|
||||
\newcommand{\RL}[1]{\beginR #1\endR}
|
||||
\newcommand{\LR}[1]{\beginL #1\endL}
|
||||
\newenvironment{RTL}{\beginR}{\endR}
|
||||
\newenvironment{LTR}{\beginL}{\endL}
|
||||
\fi
|
||||
$endif$
|
||||
$for(header-includes)$
|
||||
$header-includes$
|
||||
$endfor$
|
||||
|
||||
$if(title)$
|
||||
\title{$title$$if(thanks)$\thanks{$thanks$}$endif$}
|
||||
$endif$
|
||||
$if(subtitle)$
|
||||
\providecommand{\subtitle}[1]{}
|
||||
\subtitle{$subtitle$}
|
||||
$endif$
|
||||
$if(author)$
|
||||
\author{$for(author)$$author$$sep$ \and $endfor$}
|
||||
$endif$
|
||||
$if(institute)$
|
||||
\institute{$for(institute)$$institute$$sep$ \and $endfor$}
|
||||
$endif$
|
||||
\date{$date$}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{titlepage}
|
||||
\vspace*{\stretch{1.0}}
|
||||
\begin{center}
|
||||
\Large\textbf{What I Wish I Knew When Learning Haskell}\\
|
||||
\large\textit{Stephen Diehl}
|
||||
\end{center}
|
||||
\vspace*{\stretch{2.0}}
|
||||
\end{titlepage}
|
||||
|
||||
$if(abstract)$
|
||||
\begin{abstract}
|
||||
$abstract$
|
||||
\end{abstract}
|
||||
$endif$
|
||||
|
||||
$for(include-before)$
|
||||
$include-before$
|
||||
|
||||
$endfor$
|
||||
$if(toc)$
|
||||
{
|
||||
$if(colorlinks)$
|
||||
\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$black$endif$}
|
||||
$endif$
|
||||
\setcounter{tocdepth}{$toc-depth$}
|
||||
\tableofcontents
|
||||
|
||||
\newpage
|
||||
|
||||
}
|
||||
$endif$
|
||||
$if(lot)$
|
||||
\listoftables
|
||||
$endif$
|
||||
$if(lof)$
|
||||
\listoffigures
|
||||
$endif$
|
||||
|
||||
$body$
|
||||
|
||||
$if(natbib)$
|
||||
$if(bibliography)$
|
||||
$if(biblio-title)$
|
||||
$if(book-class)$
|
||||
\renewcommand\bibname{$biblio-title$}
|
||||
$else$
|
||||
\renewcommand\refname{$biblio-title$}
|
||||
$endif$
|
||||
$endif$
|
||||
\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}
|
||||
|
||||
$endif$
|
||||
$endif$
|
||||
$if(biblatex)$
|
||||
\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$
|
||||
|
||||
$endif$
|
||||
$for(include-after)$
|
||||
$include-after$
|
||||
|
||||
$endfor$
|
||||
\end{document}
|
@ -2,4 +2,9 @@ Basics
|
||||
======
|
||||
|
||||
```bash
|
||||
$ stack exec ghci bottoms.hs
|
||||
$ stack exec ghci defer.hs
|
||||
$ stack exec ghci fail.hs
|
||||
$ stack exec ghci stacktrace.hs
|
||||
$ stack exec ghci trace.hs
|
||||
```
|
||||
|
@ -3,4 +3,5 @@ Prelude
|
||||
|
||||
```bash
|
||||
$ stack exec ghci split.hs
|
||||
$ stack exec ghci foldable_traversable.hs
|
||||
```
|
||||
|
@ -11,8 +11,10 @@ tested-with: GHC == 7.6.3
|
||||
library
|
||||
|
||||
build-depends:
|
||||
mmorph >= 1.0 && <1.1,
|
||||
mtl >= 2.2 && <2.3,
|
||||
base >= 4.6 && <4.10
|
||||
safe >= 0.3 && <0.4,
|
||||
mmorph >= 1.0 && <1.1,
|
||||
mtl >= 2.2 && <2.3,
|
||||
transformers-base >= 0.4 && <0.5,
|
||||
base >= 4.6 && <4.10
|
||||
|
||||
default-language: Haskell2010
|
||||
|
@ -1,5 +1,5 @@
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE RebindableSyntax #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE NoMonomorphismRestriction #-}
|
||||
|
||||
import Data.IORef
|
||||
|
@ -1,2 +1,28 @@
|
||||
import Control.Monad.Trans
|
||||
import Control.Monad.State
|
||||
import Control.Monad.Morph
|
||||
|
||||
type Eval a = State [Int] a
|
||||
|
||||
runEval :: [Int] -> Eval a -> a
|
||||
runEval = flip evalState
|
||||
|
||||
pop :: Eval Int
|
||||
pop = do
|
||||
top <- gets head
|
||||
modify tail
|
||||
return top
|
||||
|
||||
push :: Int -> Eval ()
|
||||
push x = modify (x:)
|
||||
|
||||
ev1 :: Eval Int
|
||||
ev1 = do
|
||||
push 3
|
||||
push 4
|
||||
pop
|
||||
pop
|
||||
|
||||
ev2 :: StateT [Int] IO ()
|
||||
ev2 = do
|
||||
result <- hoist generalize ev1
|
||||
liftIO $ putStrLn $ "Result: " ++ show result
|
||||
|
@ -11,4 +11,5 @@ Parsing
|
||||
$ stack exec ghci parsec_operators.hs
|
||||
$ stack exec ghci parser.hs
|
||||
$ stack exec ghci simple_parser.hs
|
||||
$ stack exec ghci configurator.hs
|
||||
```
|
||||
|
89
tutorial.md
89
tutorial.md
@ -1,6 +1,6 @@
|
||||
<p class="center logo">
|
||||
![](img/title.png)
|
||||
</p>
|
||||
% What I Wish I Knew When Learning Haskell
|
||||
% Stephen Diehl
|
||||
% March 2016
|
||||
|
||||
Stephen Diehl (<a class="author" href="https://twitter.com/smdiehl">@smdiehl</a> )
|
||||
|
||||
@ -2040,17 +2040,47 @@ forM_ xs (lift . f) == lift (forM_ xs f)
|
||||
Monad Morphisms
|
||||
---------------
|
||||
|
||||
The base monad transformer package provides a ``MonadTrans`` class for lifting
|
||||
between layer:
|
||||
|
||||
```haskell
|
||||
lift :: Monad m => m a -> t m a
|
||||
```
|
||||
|
||||
But often times we need to work with and manipulate our monad transformer stack
|
||||
to either produce new transformers, modify existing ones, or extend an upstream
|
||||
library with new layers. The ``mmorph`` library provides the capacity to compose
|
||||
monad morphism transformation directly on transformer stacks. The equivalent of
|
||||
type transformer type-level map is the ``hoist`` function.
|
||||
|
||||
```haskell
|
||||
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
|
||||
embed :: Monad n => (forall a. m a -> t n a) -> t m b -> t n b
|
||||
squash :: (Monad m, MMonad t) => t (t m) a -> t m a
|
||||
```
|
||||
|
||||
TODO
|
||||
Hoist takes a *monad morphism* (a mapping a ``m a`` to a ``n a``) and applies in
|
||||
on the inner value monad of a transformer stack, transforming the value under
|
||||
the outer layer.
|
||||
|
||||
For example the monad morphism ``generalize`` takes an Identity into another
|
||||
monad ``m`` of the same index. For example this generalizes ``State s Identity``
|
||||
into ``StateT s m a``.
|
||||
|
||||
```haskell
|
||||
generalize :: Monad m => Identity a -> m a
|
||||
```
|
||||
|
||||
So we could generalize an existing transformer to lift a IO layer into it.
|
||||
|
||||
~~~~ {.haskell include="src/10-advanced-monads/mmorph.hs"}
|
||||
~~~~
|
||||
|
||||
```haskell
|
||||
embed :: Monad n => (forall a. m a -> t n a) -> t m b -> t n b
|
||||
```
|
||||
|
||||
```haskell
|
||||
squash :: (Monad m, MMonad t) => t (t m) a -> t m a
|
||||
```
|
||||
|
||||
See: [mmorph](https://hackage.haskell.org/package/mmorph)
|
||||
|
||||
@ -3018,10 +3048,31 @@ f $! x = let !vx = x in f vx
|
||||
Strict Haskell
|
||||
--------------
|
||||
|
||||
#### Strict
|
||||
As of GHC 8.0
|
||||
|
||||
#### StrictData
|
||||
|
||||
Enabling StrictData makes constructor fields strict by default on any module it
|
||||
is enabled on.
|
||||
|
||||
```haskell
|
||||
data Employee = Employee
|
||||
{ name :: T.Text
|
||||
, age :: Int
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
data Employee = Employee
|
||||
{ name :: !T.Text
|
||||
, age :: !Int
|
||||
}
|
||||
```
|
||||
|
||||
#### Strict
|
||||
|
||||
Strict implies ``-XStrictData``
|
||||
|
||||
Deepseq
|
||||
-------
|
||||
|
||||
@ -3130,7 +3181,6 @@ To get work done you probably need.
|
||||
* async
|
||||
* bytestring
|
||||
* containers
|
||||
* exceptions
|
||||
* mtl
|
||||
* stm
|
||||
* text
|
||||
@ -5039,16 +5089,14 @@ See:
|
||||
Final Interpreters
|
||||
------------------
|
||||
|
||||
TODO
|
||||
|
||||
Using typeclasses we can implement a *final interpreter* which models a set of
|
||||
extensible terms using functions bound to typeclasses rather than data
|
||||
constructors. Instances of the typeclass form interpreters over these terms.
|
||||
|
||||
For example we can write a small language that includes basic arithmetic, and
|
||||
then retroactively extend our expression language with a multiplication operator
|
||||
without changing the base. At the same time our interpreter logic
|
||||
remains invariant under extension with new expressions.
|
||||
without changing the base. At the same time our interpreter logic remains
|
||||
invariant under extension with new expressions.
|
||||
|
||||
~~~~ {.haskell include="src/14-interpreters/fext.hs"}
|
||||
~~~~
|
||||
@ -6581,12 +6629,8 @@ compiler, it can't automatically deduce the isomorphism between natural numbers
|
||||
and Peano numbers.
|
||||
|
||||
So at each of these call sites we now have a proof obligation to construct proof
|
||||
terms which rearrange the type signatures of the terms in question such that
|
||||
actual types in the error messages GHC gave us align with the expected values to
|
||||
complete the program.
|
||||
|
||||
Recall from our discussion of propositional equality from GADTs that we actually have such machinery to do
|
||||
this!
|
||||
terms. Recall from our discussion of propositional equality from GADTs that we
|
||||
actually have such machinery to construct this now.
|
||||
|
||||
~~~~ {.haskell include="src/17-promotion/reverse.hs"}
|
||||
~~~~
|
||||
@ -7117,10 +7161,11 @@ See:
|
||||
Generic Deriving
|
||||
----------------
|
||||
|
||||
Using Generics, we can ask GHC to do lots of non-trivial code generation which
|
||||
works spectacularly well in practice. Some real world examples:
|
||||
Using Generics many common libraries provide a mechanisms to derive common
|
||||
typeclass instances. Some real world examples:
|
||||
|
||||
The [hashable](http://hackage.haskell.org/package/hashable) library allows us to derive hashing functions.
|
||||
The [hashable](http://hackage.haskell.org/package/hashable) library allows us to
|
||||
derive hashing functions.
|
||||
|
||||
~~~~ {.haskell include="src/18-generics/hashable.hs"}
|
||||
~~~~
|
||||
@ -11570,7 +11615,7 @@ ver = showVersion Paths_myprog.version
|
||||
|
||||
See: [git-embed](https://hackage.haskell.org/package/git-embed)
|
||||
|
||||
</hr>
|
||||
<hr/>
|
||||
|
||||
Categories
|
||||
==========
|
||||
|
Loading…
Reference in New Issue
Block a user