Commits

Anonymous committed 20aa5ac Merge

Merged in jaxconf-edits (pull request #6)

Merge jaxconf edits to master

Comments (0)

Files changed (1)

 </section>
 
 <section class="slide">
-	<h2>One more motivating example</h2>
+	<h2>A Monad Hidden in Plain Sight</h2>
 	<div class="slide">
-	<p>Recall that there is a functor instance for functions:</p>
+	<p>Let's move beyond the <code>Option</code> example. Recall that there is a functor instance for functions:</p>
 	<pre>
 def map[A, B](fa: R => A)(f: A => B) : R => B = (x => f(fa(x)))
 	</pre>
 		<p>What about a monad instance?</p>	
 		<pre>
 implicit def FunctionMonad[R] = new Monad[({type l[a] = R=>a})#l] {
-	def flatMap[A, B](fa: R => A)(f: A => R => B) : R => B = (x => f(fa(x))(x))
+	def >>=[A, B](fa: R => A)(f: A => R => B) : R => B = (x => f(fa(x))(x))
 	...
 }
 		</pre>
 	</div>
 	<div class="slide">
-		<p>This is commonly referred to as the <code>Reader</code> monad. Here's why:</p>
-		<pre>
-val f = for {
-	t1 <- ((_:Int) + 2)
-  t2 <- ((_:Int) - 1)
-} yield t1 * t2
-		</pre>
-	<p>Think of <code>Reader</code> as a computation with a <em>read-only environment</em> (the argument) that can be supplied to produce a result.</p>
+		<p>This is commonly referred to as the <code>Reader</code> monad. It looks a bit inscrutable, so let's see where it may come in handy.</p>
 	</div>	
 </section>
 
 <section class="slide">
+	<h2>Motivating the Reader Monad</h2>
+	<div class="slide">
+		<p>Let's say we need to build absolute URLs for a web app, and the app has a base URL:</p>
+<pre class="scala">
+def makeAbs(base: AbsURL, url: URL): AbsURL = AbsURL(base + url)
+</pre>
+	</div>
+	<div class="slide">
+		<p>But this leads to a lot of repetition:</p>
+<pre class="scala">
+val links = Map("self" -> makeAbs(<strong>baseURL</strong>, "/widgets/523"),
+                "parent" -> makeAbs(<strong>baseURL</strong>, "/widgets") )
+</pre>
+	</div>
+	<div class="slide">
+		<p>Let's redefine <code>makeAbs</code> with <code>Reader</code>:</p>
+<pre class="scala">
+def makeAbs(url: URL): Reader[AbsURL, AbsURL] = 
+	Reader(base => AbsURL(base + url))
+</pre>
+	</div>
+
+	<div class="slide">
+		<p>All we've done is a syntactic switcharoo, but this lets us write:</p>
+<pre class="scala">
+(for {
+	self   <- makeAbs("/widgets/523")
+	parent <- makeAbs("/widgets")
+} yield Map("self" -> self, "parent" -> parent))(baseURL)
+</pre>
+	<p>Think of <code>Reader</code> as a computation with a <em>read-only environment</em> (the argument) that can be supplied to produce a result.</p>
+	</div>
+</section>
+
+
+<section class="slide">
 	<h2>Monad as Embedded Language</h2>
 	<div class="slide">
 		<p>Here's a <a href="http://en.wikibooks.org/wiki/Haskell/Understanding_monads">stab</a> at providing an intuition for monads. Consider:</p>
 	<div class="slide">
 	<p>Let's see why working with stacked monads gets ugly. We'll add a read-only environment to our calculator:</p>
 <pre class="scala">
-def lookup(s: String)(env: Map[String, Int]) = env.get(s) orElse parse(s)
+type Env = Map[String, Int]
+def lookup(s: String): Reader[Env, Option[Int]] = 
+	Reader(env => env.get(s) orElse parse(s))
 </pre>
 	</div>
 	<div class="slide">
 		<p>Now we'll add two numbers, using <code>Reader</code> to avoid repeating the <code>env</code> argument:</p>		
 <pre class="scala">
 for {
- xOpt <- lookup("3") _
- yOpt <- lookup("y") _
+ xOpt <- lookup("3")
+ yOpt <- lookup("y")
 } yield (for {
           x <- xOpt
           y <- yOpt
 }
 </pre>
 	</div>
-	<div class="slide">
-		<p>Our solution will involve introducing a new typeclass for <em>monad transformers</em>:</p>
-<pre class="scala">
-trait MonadTrans[F[_[_], _]] {
-  def liftM[G[_] : Monad, A](a: G[A]): F[G, A]
-}
-</pre>
-	</div>
-
 </section>
 
-
 <section class="slide">
-	<h2>More on transformers</h2>
+	<h2>Monad Transformers</h2>
 	<div class="slide">
-		<p>We're going to box a monadic computation:</p>
+		<p><em>Monad transformers</em> represent one solution. A transformer is a "wrapper" around a monadic value:</p>
 <pre class="scala">
-case class OptionT[F[+_], +A](run: F[Option[A]]) { ... }
+case class OptionT[F[+_], +A](run: F[Option[A]]) { 
+	// More to be shown shortly 
+}
 </pre>
 	</div>
 	<div class="slide">
-		<p>The boxed value exposes the underlying monad's utility functions:</p>
-		<pre code="scala">
+		<p>The wrapped value will expose the underlying monad's utility functions:</p>
+<pre code="scala">
 OptionT(List(Some(3), None, Some(4))).getOrElse(0) // List(3, 0, 4)
-		</pre>
+</pre>
 	</div>
 	<div class="slide">
-		<p>Most importantly, the boxed value is itself a monad:</p>
+		<p>Most importantly, we'll make the transformer itself a monad:</p>
 <pre class="scala">
-(for {
-	x <- OptionT(List(Some(3), None))
-	y <- List(1,2).liftM[OptionT]
-} yield x + y).run // List(Some(4), None, Some(5), None)
+case class OptionT[F[+_], +A](run: F[Option[A]]) { 
+	def >>=[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B] = 
+		new OptionT[F, B](
+			self.run >>= (a => a.match {
+								case None => F.point(None)
+								case Some(s) => f(s).run
+							}))  
+	...
+}
 </pre>
 		<p>We can stack transformers arbitrarily deep!</p>
 	</div>
 		<p>Let's clean up our previous example with <code>ReaderT</code>. Recall we had:
 <pre class="scala">
 for {
- xOpt <- lookup("3") _
- yOpt <- lookup("y") _
+ xOpt <- lookup("3") 
+ yOpt <- lookup("y") 
 } yield (for {
           x <- xOpt
           y <- yOpt
 		<p>With <code>ReaderT</code>:
 <pre class="scala">
 for {
-	x <- Kleisli(lookup("3") _)
-	y <- Kleisli(lookup("y") _)
+	x <- Kleisli(lookup("3"))
+	y <- Kleisli(lookup("y"))
 } yield x + y
 </pre>
 	<p style="font-size:60%">(Much nicer!)</p>
 </section>
 
 <section class="slide">
+	<h2>The Monad Transformer Typeclass</h2>
+	<div class="slide">
+		<p>There is a typeclass for monad transformers, which defines a single operation <code>liftM</code>:</p>
+<pre class="scala">
+trait MonadTrans[F[_[_], _]] {
+  def liftM[G[_] : Monad, A](a: G[A]): F[G, A]
+}
+</pre>
+	</div>
+	<div class="slide">
+		<p><code>liftM</code> gives us the ability to "lift" computations in the base monad into the transformed monad:</p>
+<pre class="scala">
+(for {
+	x <- OptionT(List(Some(3), None))
+	y <- List(1,2).liftM[OptionT]
+} yield x + y).run // List(Some(4), None, Some(5), None)
+</pre>
+	</div>
+</section>
+
+<section class="slide">
 	<h2>Another take on composing monads</h2>
 	<div class="slide">
-		<p>An alternative formulation of <code>Monad</code> provides some insight into the composition problem. Instead of <code>bind</code>, it's sufficient to implement <code>join</code>:<p>
+		<p>An alternative formulation of <code>Monad</code> provides some insight into the composition problem. Instead of bind (<code>>>=</code>), it's sufficient to implement a method called <code>join</code>:<p>
 		<pre class="scala">
 trait Monad[F[_]] extends Applicative {
 	def join[A](fa: F[F[A]]): F[A]
 		<p style="font-size: 60%">(Whew!)</p>			
 	</div>
 	<div class="slide">
-		<p>The <code>join</code> methods defined on <code>M</code> and <code>N</code> don't help, because they're "blocked" by the other monad. But what if we could "commute" the monads?
+		<p>The <code>join</code> methods defined on <code>M</code> and <code>N</code> don't help, because they're "blocked" by the other monad. But what if we could "commute" the monads, or change the sequence of the <code>M</code>'s and <code>N</code>'s?
 <pre class="scala">
-def commute[A](a: M[N[A]]): N[M[A]]
+def sequence[A](a: M[N[A]]): N[M[A]]
 </pre>
 	</div>
 	<div class="slide">
-		<p>This works! It's possible to define monad composition given the <code>commute</code> function.</p>
+		<p>This works! It's possible to define monad composition given the <code>sequence</code> function.</p>
 	</div>
 </section>
 
 <section class="slide">
 	<h2>Introducing Traverse</h2>
 	<div class="slide">
-	<p>The <code>Traverse</code> typeclass provides exactly this: the ability to commute two functors</p>
+	<p>The <code>Traverse</code> typeclass provides exactly this. It gives the ability to commute two functors:</p>
 	<pre class="scala">
 trait Traverse[F[_]] extends Functor {
 	def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]]
 <section class="slide">
 	<h2>Monad composition for free</h2>
 	<div class="slide">
-		<p>Assuming we also have a <code>Traverse</code> requirement on monads <code>M</code> and <code>N</code>, we can get a composed monad for "free": </p>
+		<p>Assuming we also have a <code>Traverse</code> requirement on monad <code>N</code>, we can get a composed monad for "free": </p>
 <pre class="scala">
 implicit val ComposedMonad[M: Monad, N: Monad: Traverse] = new Monad[...] {
 	def >>=[A, B](fa: M[N[A]])(f: A => M[N[B]]) : M[N[B]] = // ???
 		<h6 class="slide">Exercise: Implement <code> >>= </code> for <code>ComposedMonad</code>.</h6>
 	</div>
 	<div class="slide">
-		<p>This can be used to supply monad transformer implementations. Sometimes, though, this "free" transformer doesn't have the semantics we want.		
+		<p>This could be used to supply monad transformer implementations, though the "free" transformer doesn't always give the semantics we want. Note that scalaz doesn't use this "free" formulation.
 	</div>
 
 </section>