Skip to content
Browse files

Final notes.

  • Loading branch information...
1 parent 130c109 commit d7121efcaa74d8a612507a05339cfa40de6bfe78 @bos committed
Showing with 346 additions and 12 deletions.
  1. +21 −0 notes/l9/Table.hs
  2. +114 −3 notes/l9/monads.md
  3. +5 −0 www/notes/index.html
  4. +55 −2 www/notes/monads-slides.html
  5. +35 −2 www/notes/monads.html
  6. +114 −3 www/notes/monads.md
  7. +1 −1 www/sched/index.html
  8. +1 −1 www/sched/sched.html
View
21 notes/l9/Table.hs
@@ -0,0 +1,21 @@
+import Control.Applicative
+import Control.Monad.State
+import qualified Data.Map as Map
+
+type Address = String
+
+data Number = N !(Map.Map Address Int) !Int
+ deriving (Show)
+
+renumber :: [(Address,Address)] -> [(Int,Int)]
+renumber xs = evalState (mapM pair xs) (N Map.empty 0)
+ where pair (x,y) = (,) <$> number x <*> number y
+
+number :: Address -> State Number Int
+number a = do
+ N m i <- get
+ case Map.lookup a m of
+ Just j -> return j
+ Nothing -> do let i' = i + 1
+ put $! N (Map.insert a i m) i'
+ return i'
View
117 notes/l9/monads.md
@@ -704,7 +704,7 @@ the fundep:
class (Monad m) => MonadState s m {- ... -}
~~~~
-And suppose we were to try to typecheck these type signatures:
+And if we were to try to typecheck these type signatures:
~~~~ {.haskell}
modify' :: MonadState s m => (s -> (a,s)) -> m a
@@ -713,5 +713,116 @@ guess :: RandomGen g => State g Double
~~~~
Without the fundep, the compiler would choke on these, because it has
-no information to tell it that the `g` parameter to `State` is related
-to the `s` parameter to `MonadState`.
+no information to assure it that the `g` parameter to `State` is
+related to the `s` parameter to `MonadState`.
+
+
+# Using the state monad
+
+Suppose we're running a social network, and we want to know who is
+connected to whom.
+
+To build a matrix of connections, we need to represent user addresses
+as integer positions on each axis.
+
+~~~~ {.haskell}
+import Control.Applicative
+import Control.Monad.State
+import qualified Data.Map as Map
+
+type Address = String
+
+data Number = N !(Map.Map Address Int) !Int
+ deriving (Show)
+~~~~
+
+The `Number` type is the state we'll use (and possibly modify) while
+numbering.
+
+
+# Getting started
+
+This is the top-level address-numbering function.
+
+~~~~ {.haskell}
+renumber :: [(Address,Address)] -> [(Int,Int)]
+renumber xs = evalState (mapM pair xs) (N Map.empty 0)
+ where pair (x,y) = (,) <$> number x <*> number y
+~~~~
+
+This depends on a few functions we haven't seen before.
+
+Monadic mapping:
+
+~~~~ {.haskell}
+mapM :: Monad m => (a -> m b) -> [a] -> m [b]
+~~~~
+
+The second of the three "run me a state monad" functions:
+
+~~~~ {.haskell}
+runState :: State s a -> s -> (a, s)
+evalState :: State s a -> s -> a
+execState :: State s a -> s -> s
+~~~~
+
+The super-useful `<$>` operator is nothing but shorthand for `fmap`.
+
+And finally, a use in the wild for the `<*>` operator!
+
+
+# What about the number function?
+
+This is where the real work happens.
+
+If an address is already stored in the numbering map, our function
+returns the number associated with the address.
+
+~~~~ {.haskell}
+number :: Address -> State Number Int
+number addr = do
+ N numMap highest <- get
+ case Map.lookup addr numMap of
+ Just j -> return j
+ Nothing -> do let highest' = highest + 1
+ newMap = Map.insert addr highest numMap
+ put $! N newMap highest'
+ return highest'
+~~~~
+
+Otherwise, we increment the highest number seen, associate the
+previous number with the address, store the modified state, and return
+the number.
+
+
+# The Reader monad
+
+Reader is another widely used monad, and in fact we've already seen a
+form of it:
+
+~~~~ {.haskell}
+((->) a)
+~~~~
+
+This is best understood in comparison to the state monad:
+
+* In `State`, every function got passed a piece of state that it could
+ transform. This lets us achieve shared mutable state.
+
+* In `Reader`, every function is passed a piece of state
+ that it is not allowed to change. This lets us achieve shared
+ *read-only* state.
+
+As an example of a piece of immutable data that we might want to
+thread around all over the place, think "application configuration".
+
+The reader monad lets us hide the plumbing of passing that information
+around.
+
+
+# Reader vs reader
+
+The `Reader` type is defined in `Control.Monad.Reader`.
+
+The *only* difference between it and `((->) a)` is that `Reader` is a
+`newtype` wrapper around `((->) a)`.
View
5 www/notes/index.html
@@ -52,6 +52,11 @@
[<a href="laziness-slides.html">slides</a>,
<a href="laziness.md">source</a>]
</li>
+<li id="l9">
+ <a href="monads.html">Monads and more</a>
+ [<a href="monads-slides.html">slides</a>,
+ <a href="monads.md">source</a>]
+</li>
</ol>
<p>
View
57 www/notes/monads-slides.html
@@ -418,9 +418,62 @@ <h1 class="title">Monads and more</h1>
<h1>Why functional dependencies?</h1>
<p>Suppose we were to write a simpler multi-parameter type class, without the fundep:</p>
<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">class</span> (<span class="kw">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadState</span> s m <span class="co">{- ... -}</span></code></pre>
-<p>And suppose we were to try to typecheck these type signatures:</p>
+<p>And if we were to try to typecheck these type signatures:</p>
<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">modify' </span><span class="ot">::</span> <span class="dt">MonadState</span> s m <span class="ot">=&gt;</span> (s <span class="ot">-&gt;</span> (a,s)) <span class="ot">-&gt;</span> m a<br /><br /><span class="ot">guess </span><span class="ot">::</span> <span class="dt">RandomGen</span> g <span class="ot">=&gt;</span> <span class="dt">State</span> g <span class="dt">Double</span></code></pre>
-<p>Without the fundep, the compiler would choke on these, because it has no information to tell it that the <code>g</code> parameter to <code>State</code> is related to the <code>s</code> parameter to <code>MonadState</code>.</p>
+<p>Without the fundep, the compiler would choke on these, because it has no information to assure it that the <code>g</code> parameter to <code>State</code> is related to the <code>s</code> parameter to <code>MonadState</code>.</p>
+</div>
+
+<div class="slide">
+
+<h1>Using the state monad</h1>
+<p>Suppose we're running a social network, and we want to know who is connected to whom.</p>
+<p>To build a matrix of connections, we need to represent user addresses as integer positions on each axis.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">import</span> <span class="dt">Control.Applicative</span><br /><span class="kw">import</span> <span class="dt">Control.Monad.State</span><br /><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">Map</span><br /><br /><span class="kw">type</span> <span class="dt">Address</span> <span class="fu">=</span> <span class="dt">String</span><br /><br /><span class="kw">data</span> <span class="dt">Number</span> <span class="fu">=</span> <span class="dt">N</span> <span class="fu">!</span>(<span class="dt">Map.Map</span> <span class="dt">Address</span> <span class="dt">Int</span>) <span class="fu">!</span><span class="dt">Int</span><br /> <span class="kw">deriving</span> (<span class="kw">Show</span>)</code></pre>
+<p>The <code>Number</code> type is the state we'll use (and possibly modify) while numbering.</p>
+</div>
+
+<div class="slide">
+
+<h1>Getting started</h1>
+<p>This is the top-level address-numbering function.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">renumber </span><span class="ot">::</span> [(<span class="dt">Address</span>,<span class="dt">Address</span>)] <span class="ot">-&gt;</span> [(<span class="dt">Int</span>,<span class="dt">Int</span>)]<br />renumber xs <span class="fu">=</span> evalState (<span class="fu">mapM</span> pair xs) (<span class="dt">N</span> Map.empty <span class="dv">0</span>)<br /> <span class="kw">where</span> pair (x,y) <span class="fu">=</span> (,) <span class="fu">&lt;$&gt;</span> number x <span class="fu">&lt;*&gt;</span> number y</code></pre>
+<p>This depends on a few functions we haven't seen before.</p>
+<p>Monadic mapping:</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="fu">mapM</span><span class="ot"> </span><span class="ot">::</span> <span class="kw">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> m [b]</code></pre>
+<p>The second of the three &quot;run me a state monad&quot; functions:</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">runState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> (a, s)<br /><span class="ot">evalState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> a<br /><span class="ot">execState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> s</code></pre>
+<p>The super-useful <code>&lt;$&gt;</code> operator is nothing but shorthand for <code>fmap</code>.</p>
+<p>And finally, a use in the wild for the <code>&lt;*&gt;</code> operator!</p>
+</div>
+
+<div class="slide">
+
+<h1>What about the number function?</h1>
+<p>This is where the real work happens.</p>
+<p>If an address is already stored in the numbering map, our function returns the number associated with the address.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">number </span><span class="ot">::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">State</span> <span class="dt">Number</span> <span class="dt">Int</span><br />number addr <span class="fu">=</span> <span class="kw">do</span><br /> <span class="dt">N</span> numMap highest <span class="ot">&lt;-</span> get<br /> <span class="kw">case</span> Map.lookup addr numMap <span class="kw">of</span><br /> <span class="kw">Just</span> j <span class="ot">-&gt;</span> <span class="fu">return</span> j<br /> <span class="kw">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">do</span> <span class="kw">let</span> highest' <span class="fu">=</span> highest <span class="fu">+</span> <span class="dv">1</span><br /> newMap <span class="fu">=</span> Map.insert addr highest numMap<br /> put <span class="fu">$!</span> <span class="dt">N</span> newMap highest'<br /> <span class="fu">return</span> highest'</code></pre>
+<p>Otherwise, we increment the highest number seen, associate the previous number with the address, store the modified state, and return the number.</p>
+</div>
+
+<div class="slide">
+
+<h1>The Reader monad</h1>
+<p>Reader is another widely used monad, and in fact we've already seen a form of it:</p>
+<pre class="sourceCode"><code class="sourceCode haskell">((<span class="ot">-&gt;</span>) a)</code></pre>
+<p>This is best understood in comparison to the state monad:</p>
+<ul>
+<li><p>In <code>State</code>, every function got passed a piece of state that it could transform. This lets us achieve shared mutable state.</p></li>
+<li><p>In <code>Reader</code>, every function is passed a piece of state that it is not allowed to change. This lets us achieve shared <em>read-only</em> state.</p></li>
+</ul>
+<p>As an example of a piece of immutable data that we might want to thread around all over the place, think &quot;application configuration&quot;.</p>
+<p>The reader monad lets us hide the plumbing of passing that information around.</p>
+</div>
+
+<div class="slide">
+
+<h1>Reader vs reader</h1>
+<p>The <code>Reader</code> type is defined in <code>Control.Monad.Reader</code>.</p>
+<p>The <em>only</em> difference between it and <code>((-&gt;) a)</code> is that <code>Reader</code> is a <code>newtype</code> wrapper around <code>((-&gt;) a)</code>.</p>
</div>
</body>
</html>
View
37 www/notes/monads.html
@@ -251,8 +251,41 @@ <h1 id="a-new-guesser">A new guesser</h1>
<h1 id="why-functional-dependencies">Why functional dependencies?</h1>
<p>Suppose we were to write a simpler multi-parameter type class, without the fundep:</p>
<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">class</span> (<span class="kw">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadState</span> s m <span class="co">{- ... -}</span></code></pre>
-<p>And suppose we were to try to typecheck these type signatures:</p>
+<p>And if we were to try to typecheck these type signatures:</p>
<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">modify' </span><span class="ot">::</span> <span class="dt">MonadState</span> s m <span class="ot">=&gt;</span> (s <span class="ot">-&gt;</span> (a,s)) <span class="ot">-&gt;</span> m a<br /><br /><span class="ot">guess </span><span class="ot">::</span> <span class="dt">RandomGen</span> g <span class="ot">=&gt;</span> <span class="dt">State</span> g <span class="dt">Double</span></code></pre>
-<p>Without the fundep, the compiler would choke on these, because it has no information to tell it that the <code>g</code> parameter to <code>State</code> is related to the <code>s</code> parameter to <code>MonadState</code>.</p>
+<p>Without the fundep, the compiler would choke on these, because it has no information to assure it that the <code>g</code> parameter to <code>State</code> is related to the <code>s</code> parameter to <code>MonadState</code>.</p>
+<h1 id="using-the-state-monad">Using the state monad</h1>
+<p>Suppose we're running a social network, and we want to know who is connected to whom.</p>
+<p>To build a matrix of connections, we need to represent user addresses as integer positions on each axis.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">import</span> <span class="dt">Control.Applicative</span><br /><span class="kw">import</span> <span class="dt">Control.Monad.State</span><br /><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">Map</span><br /><br /><span class="kw">type</span> <span class="dt">Address</span> <span class="fu">=</span> <span class="dt">String</span><br /><br /><span class="kw">data</span> <span class="dt">Number</span> <span class="fu">=</span> <span class="dt">N</span> <span class="fu">!</span>(<span class="dt">Map.Map</span> <span class="dt">Address</span> <span class="dt">Int</span>) <span class="fu">!</span><span class="dt">Int</span><br /> <span class="kw">deriving</span> (<span class="kw">Show</span>)</code></pre>
+<p>The <code>Number</code> type is the state we'll use (and possibly modify) while numbering.</p>
+<h1 id="getting-started">Getting started</h1>
+<p>This is the top-level address-numbering function.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">renumber </span><span class="ot">::</span> [(<span class="dt">Address</span>,<span class="dt">Address</span>)] <span class="ot">-&gt;</span> [(<span class="dt">Int</span>,<span class="dt">Int</span>)]<br />renumber xs <span class="fu">=</span> evalState (<span class="fu">mapM</span> pair xs) (<span class="dt">N</span> Map.empty <span class="dv">0</span>)<br /> <span class="kw">where</span> pair (x,y) <span class="fu">=</span> (,) <span class="fu">&lt;$&gt;</span> number x <span class="fu">&lt;*&gt;</span> number y</code></pre>
+<p>This depends on a few functions we haven't seen before.</p>
+<p>Monadic mapping:</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="fu">mapM</span><span class="ot"> </span><span class="ot">::</span> <span class="kw">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> m [b]</code></pre>
+<p>The second of the three &quot;run me a state monad&quot; functions:</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">runState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> (a, s)<br /><span class="ot">evalState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> a<br /><span class="ot">execState </span><span class="ot">::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> s</code></pre>
+<p>The super-useful <code>&lt;$&gt;</code> operator is nothing but shorthand for <code>fmap</code>.</p>
+<p>And finally, a use in the wild for the <code>&lt;*&gt;</code> operator!</p>
+<h1 id="what-about-the-number-function">What about the number function?</h1>
+<p>This is where the real work happens.</p>
+<p>If an address is already stored in the numbering map, our function returns the number associated with the address.</p>
+<pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">number </span><span class="ot">::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">State</span> <span class="dt">Number</span> <span class="dt">Int</span><br />number addr <span class="fu">=</span> <span class="kw">do</span><br /> <span class="dt">N</span> numMap highest <span class="ot">&lt;-</span> get<br /> <span class="kw">case</span> Map.lookup addr numMap <span class="kw">of</span><br /> <span class="kw">Just</span> j <span class="ot">-&gt;</span> <span class="fu">return</span> j<br /> <span class="kw">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">do</span> <span class="kw">let</span> highest' <span class="fu">=</span> highest <span class="fu">+</span> <span class="dv">1</span><br /> newMap <span class="fu">=</span> Map.insert addr highest numMap<br /> put <span class="fu">$!</span> <span class="dt">N</span> newMap highest'<br /> <span class="fu">return</span> highest'</code></pre>
+<p>Otherwise, we increment the highest number seen, associate the previous number with the address, store the modified state, and return the number.</p>
+<h1 id="the-reader-monad">The Reader monad</h1>
+<p>Reader is another widely used monad, and in fact we've already seen a form of it:</p>
+<pre class="sourceCode"><code class="sourceCode haskell">((<span class="ot">-&gt;</span>) a)</code></pre>
+<p>This is best understood in comparison to the state monad:</p>
+<ul>
+<li><p>In <code>State</code>, every function got passed a piece of state that it could transform. This lets us achieve shared mutable state.</p></li>
+<li><p>In <code>Reader</code>, every function is passed a piece of state that it is not allowed to change. This lets us achieve shared <em>read-only</em> state.</p></li>
+</ul>
+<p>As an example of a piece of immutable data that we might want to thread around all over the place, think &quot;application configuration&quot;.</p>
+<p>The reader monad lets us hide the plumbing of passing that information around.</p>
+<h1 id="reader-vs-reader">Reader vs reader</h1>
+<p>The <code>Reader</code> type is defined in <code>Control.Monad.Reader</code>.</p>
+<p>The <em>only</em> difference between it and <code>((-&gt;) a)</code> is that <code>Reader</code> is a <code>newtype</code> wrapper around <code>((-&gt;) a)</code>.</p>
</body>
</html>
View
117 www/notes/monads.md
@@ -704,7 +704,7 @@ the fundep:
class (Monad m) => MonadState s m {- ... -}
~~~~
-And suppose we were to try to typecheck these type signatures:
+And if we were to try to typecheck these type signatures:
~~~~ {.haskell}
modify' :: MonadState s m => (s -> (a,s)) -> m a
@@ -713,5 +713,116 @@ guess :: RandomGen g => State g Double
~~~~
Without the fundep, the compiler would choke on these, because it has
-no information to tell it that the `g` parameter to `State` is related
-to the `s` parameter to `MonadState`.
+no information to assure it that the `g` parameter to `State` is
+related to the `s` parameter to `MonadState`.
+
+
+# Using the state monad
+
+Suppose we're running a social network, and we want to know who is
+connected to whom.
+
+To build a matrix of connections, we need to represent user addresses
+as integer positions on each axis.
+
+~~~~ {.haskell}
+import Control.Applicative
+import Control.Monad.State
+import qualified Data.Map as Map
+
+type Address = String
+
+data Number = N !(Map.Map Address Int) !Int
+ deriving (Show)
+~~~~
+
+The `Number` type is the state we'll use (and possibly modify) while
+numbering.
+
+
+# Getting started
+
+This is the top-level address-numbering function.
+
+~~~~ {.haskell}
+renumber :: [(Address,Address)] -> [(Int,Int)]
+renumber xs = evalState (mapM pair xs) (N Map.empty 0)
+ where pair (x,y) = (,) <$> number x <*> number y
+~~~~
+
+This depends on a few functions we haven't seen before.
+
+Monadic mapping:
+
+~~~~ {.haskell}
+mapM :: Monad m => (a -> m b) -> [a] -> m [b]
+~~~~
+
+The second of the three "run me a state monad" functions:
+
+~~~~ {.haskell}
+runState :: State s a -> s -> (a, s)
+evalState :: State s a -> s -> a
+execState :: State s a -> s -> s
+~~~~
+
+The super-useful `<$>` operator is nothing but shorthand for `fmap`.
+
+And finally, a use in the wild for the `<*>` operator!
+
+
+# What about the number function?
+
+This is where the real work happens.
+
+If an address is already stored in the numbering map, our function
+returns the number associated with the address.
+
+~~~~ {.haskell}
+number :: Address -> State Number Int
+number addr = do
+ N numMap highest <- get
+ case Map.lookup addr numMap of
+ Just j -> return j
+ Nothing -> do let highest' = highest + 1
+ newMap = Map.insert addr highest numMap
+ put $! N newMap highest'
+ return highest'
+~~~~
+
+Otherwise, we increment the highest number seen, associate the
+previous number with the address, store the modified state, and return
+the number.
+
+
+# The Reader monad
+
+Reader is another widely used monad, and in fact we've already seen a
+form of it:
+
+~~~~ {.haskell}
+((->) a)
+~~~~
+
+This is best understood in comparison to the state monad:
+
+* In `State`, every function got passed a piece of state that it could
+ transform. This lets us achieve shared mutable state.
+
+* In `Reader`, every function is passed a piece of state
+ that it is not allowed to change. This lets us achieve shared
+ *read-only* state.
+
+As an example of a piece of immutable data that we might want to
+thread around all over the place, think "application configuration".
+
+The reader monad lets us hide the plumbing of passing that information
+around.
+
+
+# Reader vs reader
+
+The `Reader` type is defined in `Control.Monad.Reader`.
+
+The *only* difference between it and `((->) a)` is that `Reader` is a
+`newtype` wrapper around `((->) a)`.
View
2 www/sched/index.html
@@ -106,7 +106,7 @@
</td>
<td class="sylcol" valign=top>
-<b>Monads &amp; parsers</b> (bos)<br>
+<b><a href="../notes/monads-slides.html">Monads and more</a></b> (bos)<br>
</td>
<td class="sylcol" valign=top>
View
2 www/sched/sched.html
@@ -35,7 +35,7 @@
</td>
<td class="sylcol" valign=top>
-<b>Monads &amp; parsers</b> (bos)<br>
+<b><a href="../notes/monads-slides.html">Monads and more</a></b> (bos)<br>
</td>
<td class="sylcol" valign=top>

0 comments on commit d7121ef

Please sign in to comment.
Something went wrong with that request. Please try again.