Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Reader is defined as:</p> <pre><code>newtype Reader r a = Reader { runReader :: r -&gt; a } </code></pre> <p>So it's really just a function of type <code>r -&gt; a</code> with some extra encapsulation. This makes sense, as the Reader really just provides an extra input to all the actions in the monad.</p> <p>If we strip the encapsulation and only use the <code>r -&gt; a</code> function, the types of the monadic functions are:</p> <pre><code>return :: a -&gt; (r -&gt; a) -- or: a -&gt; r -&gt; a (&gt;&gt;=) :: (r -&gt; a) -&gt; (a -&gt; (r -&gt; b)) -&gt; (r -&gt; b) -- or: (r -&gt; a) -&gt; (a -&gt; r -&gt; b) -&gt; r -&gt; b </code></pre> <p>Looking at this it is a lot easier to see what is required of us. If you look at the type <code>a -&gt; (r -&gt; a)</code> and see that this is equivalent to <code>a -&gt; r -&gt; a</code>, you can see that you can look at this function in two ways. One is that you take an argument of <code>a</code> and return a function of type <code>r -&gt; a</code>, the other is to look at is as a function that takes an <code>a</code> and an <code>r</code> and returns an <code>a</code>. You can implement return using either of these views:</p> <pre><code>return a = \r -&gt; a -- or: return a r = a </code></pre> <p>The bind is trickier, but the same logic applies. In the first type signature I gave, it is not immediately evident that the third <code>r</code> in the type is actually also an input, while the second type signature makes this very easy to see. So let's start with implementing the second type signature:</p> <pre><code>(&gt;&gt;=) rToA aAndRToB r = ... </code></pre> <p>So we have a value of type <code>r</code>, a function of type <code>r -&gt; a</code> and a function of type <code>a -&gt; r -&gt; b</code> and our goal is to make a value of type <code>b</code> out of that. The only <code>b</code> in our input is in the <code>a -&gt; r -&gt; b</code> function so we will need to use that, but we do not have an <code>a</code> to feed it, so we need to get one. The <code>r -&gt; a</code> function can provide one, if we have an <code>r</code> for it. We do have an <code>r</code>, it's our third input. So we can simply apply the functions until we get our <code>b</code>:</p> <pre><code>(&gt;&gt;=) rToA aAndRToB r = b where a = rToA r b = aAndRToB a r </code></pre> <p>Here you can see that we provide the <code>r</code>-value to every action (which is the goal of the Reader monad) while also chaining the <code>a</code>-value from one action to the next (which is the goal of <code>(&gt;&gt;=)</code>). You can also write this in a way that mimics the first type signature like this:</p> <pre><code>(&gt;&gt;=) rToA aToRToB = \r -&gt; (aToRToB (rToA r)) r </code></pre> <p>which if you rename the variables looks very similar to the definition of Reader's bind, but without using <code>Reader</code> and <code>runReader</code>:</p> <pre><code>m &gt;&gt;= k = /r -&gt; k (m r) r </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload