<div dir="ltr">I think I&#39;m starting to get the &quot;way of arrows&quot;.<div><br></div><div>My implementation was incorrect. I&#39;ve seen it with the hand made test listed below [1].</div><div>The output of &quot;first arrA&quot; and &quot;first arrB&quot; should be joined together and form a new stream with the length of the shortest output of both (&quot;arrA *** arrB&quot;), and this wasn&#39;t happening.</div>

<div><br></div><div>I&#39;ve found package &quot;streamproc&quot; at Hackage and that gave me some insights.</div><div>Yet I think &quot;streamproc&quot; is also wrong, as it does not buffer the second stream.</div><div>
You can check it at line 58 of SP.hs [3] that it ignores the first element of the pair.</div>
<div>But I didn&#39;t write a test to check what is the implication of this, I&#39;ll try to do this as a next step into understanding arrows.</div><div><br></div><div>That exercise really helped me!</div><div><br></div>
<div>
My new implementation, wich I think is correct now, is listed below [2].</div><div><br></div><div>Thanks!</div><div><br></div><div>Thiago</div><div><br></div><div><br></div><div>[1]:</div><div><div>inputA :: [String]</div>

<div>inputA = [&quot;a&quot;, &quot;b&quot;, &quot;hello&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;hello&quot;, &quot;f&quot;, &quot;g&quot;, &quot;e&quot;, &quot;x&quot;]</div><div><br></div><div>arrA :: SP String String</div>

<div>arrA = Get (\a -&gt; if a == &quot;hello&quot; then (Put a (Put &quot;world&quot; arrA))</div><div>                                  else (Put &quot;unknown&quot; arrA))</div><div><br></div><div>arrB :: SP String String</div>

<div>arrB = Get (\a -&gt; if a == &quot;my&quot; then (Get (\a -&gt; if a == &quot;name&quot; then (Get (\a -&gt; if a == &quot;is&quot; then Get (\a -&gt; Put (&quot;name: &quot; ++ a) arrB)</div><div>                                                                                             else arrB))</div>

<div>                                                               else arrB))</div><div>                               else arrB)</div><div><br></div><div>inputB :: [String]</div><div>inputB = [&quot;a&quot;, &quot;b&quot;, &quot;my&quot;, &quot;name&quot;, &quot;is&quot;, &quot;thiago&quot;, &quot;and&quot;, &quot;I&quot;, &quot;am&quot;, &quot;so&quot;, &quot;cool&quot;]</div>

<div><br></div><div>inputAB :: [(String, String)]</div><div>inputAB = zip inputA inputB</div><div><br></div><div>main :: IO ()</div><div>main = let actualOutputB = runSP arrB inputB</div><div>           actualOutputB1 = runSP (first arrB) (zip inputB (repeat &quot;a&quot;))</div>

<div>           actualOutputA = runSP arrA inputA</div><div>           actualOutputA1 = runSP (first arrA) (zip inputA (repeat &quot;a&quot;))</div><div>           actualOutputAB = runSP (arrA *** arrB) inputAB</div><div>

       in do putStrLn $ &quot;inputAB: &quot; ++ show inputAB</div><div>             putStrLn $ &quot;outputA: &quot; ++ show actualOutputA</div><div>             putStrLn $ &quot;outputA1: &quot; ++ show actualOutputA1</div>

<div>             putStrLn $ &quot;outputB: &quot; ++ show actualOutputB</div><div>             putStrLn $ &quot;outputB1: &quot; ++ show actualOutputB1</div><div>             putStrLn $ &quot;outputAB: &quot; ++ show actualOutputAB</div>

</div><div><br></div><div><br></div><div><br></div><div>[2]:</div><div><div>module SP where</div><div><br></div><div>import Prelude hiding (id, (.))</div><div>import Control.Category</div><div>import Control.Arrow</div><div>

import Test.QuickCheck</div><div><br></div><div>data SP a b = Put b (SP a b) | Get (a -&gt; SP a b)</div><div><br></div><div>runSP :: SP a b -&gt; [a] -&gt; [b]</div><div>runSP (Put b s) as = b:runSP s as</div><div>runSP (Get k) (a:as) = runSP (k a) as</div>

<div>runSP (Get k) [] = []</div><div><br></div><div>compose :: SP b c -&gt; SP a b -&gt; SP a c</div><div>compose (Put a s) g = Put a (compose s g)</div><div>compose (Get k) (Put a s) = compose (k a) s</div><div>compose f (Get k) = Get (\a -&gt; compose f (k a))</div>

<div><br></div><div>instance Category SP where</div><div>  id = arr id</div><div>  (.) = compose</div><div><br></div><div>instance Arrow SP where</div><div>  arr f = Get (\a -&gt; Put (f a) (arr f))</div><div>  first = queued empty empty</div>

<div><br></div><div>queued :: Queue a -&gt; Queue c -&gt; SP a b -&gt; SP (a, c) (b, c)</div><div>queued qa qc (Put a s) = case pop qc of Nothing -&gt; Get (\(a&#39;, c) -&gt; Put (a, c) (queued (push a&#39; qa) qc s))</div>

<div>                                        Just (c, qc&#39;) -&gt; Put (a, c) (queued qa qc&#39; s)</div><div>queued qa qc (Get k) = case pop qa of Nothing -&gt; Get (\(a, c) -&gt; queued qa (push c qc) (k a))</div><div>

                                      Just (a, qa&#39;) -&gt; queued qa&#39; qc (k a)</div><div><br></div><div>data Queue a = Queue [a]</div><div><br></div><div>empty :: Queue a</div><div>empty = Queue []</div><div><br></div>

<div>push :: a -&gt; Queue a -&gt; Queue a</div><div>push a (Queue as) = Queue (a:as)</div><div><br></div><div>pop :: Queue a -&gt; Maybe (a, Queue a)</div><div>pop (Queue []) = Nothing</div><div>pop (Queue (a:as)) = Just (a, Queue as)</div>

<div><br></div><div>delayed :: (a, c) -&gt; SP a b -&gt; SP (a, c) (b, c)</div><div>delayed (a, c) (Put b s) = Put (b, c) (delayed (a, c) s)</div><div>delayed (a, c) (Get k) = firstWithValue (k a) c</div><div><br></div><div>

firstWithValue :: SP a b -&gt; c -&gt; SP (a, c) (b, c)</div><div>firstWithValue (Put a s) c = Put (a, c) (firstWithValue s c)</div><div>firstWithValue (Get k) _ = Get (\(a, c) -&gt; firstWithValue (k a) c)</div><div><br>

</div><div>input :: [(String, String)]</div><div>input = [(&quot;a1&quot;, &quot;a2&quot;), (&quot;b1&quot;, &quot;b2&quot;), (&quot;c1&quot;, &quot;c2&quot;), (&quot;d1&quot;, &quot;d2&quot;)]</div><div><br></div><div>myArrow :: SP (String, String) (String, String)</div>

<div>myArrow = (delay &quot;db1&quot; &gt;&gt;&gt; delay &quot;da1&quot;) *** (delay &quot;db2&quot; &gt;&gt;&gt; delay &quot;da2&quot;)</div><div><br></div><div>delay :: a -&gt; SP a a</div><div>delay b = Put b (arr id)</div>

<div><br></div><div>inputA :: [String]</div><div>inputA = [&quot;a&quot;, &quot;b&quot;, &quot;hello&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;hello&quot;, &quot;f&quot;, &quot;g&quot;, &quot;e&quot;, &quot;x&quot;]</div>

<div><br></div><div>arrA :: SP String String</div><div>arrA = Get (\a -&gt; if a == &quot;hello&quot; then (Put a (Put &quot;world&quot; arrA))</div><div>                                  else (Put &quot;unknown&quot; arrA))</div>

<div><br></div><div>arrB :: SP String String</div><div>arrB = Get (\a -&gt; if a == &quot;my&quot; then (Get (\a -&gt; if a == &quot;name&quot; then (Get (\a -&gt; if a == &quot;is&quot; then Get (\a -&gt; Put (&quot;name: &quot; ++ a) arrB)</div>

<div>                                                                                             else arrB))</div><div>                                                               else arrB))</div><div>                               else arrB)</div>

<div><br></div><div>inputB :: [String]</div><div>inputB = [&quot;a&quot;, &quot;b&quot;, &quot;my&quot;, &quot;name&quot;, &quot;is&quot;, &quot;thiago&quot;, &quot;and&quot;, &quot;I&quot;, &quot;am&quot;, &quot;so&quot;, &quot;cool&quot;]</div>

<div><br></div><div>inputAB :: [(String, String)]</div><div>inputAB = zip inputA inputB</div><div><br></div><div>main :: IO ()</div><div>main = let actualOutputB = runSP arrB inputB</div><div>           actualOutputB1 = runSP (first arrB) (zip inputB (repeat &quot;a&quot;))</div>

<div>           actualOutputA = runSP arrA inputA</div><div>           actualOutputA1 = runSP (first arrA) (zip inputA (repeat &quot;a&quot;))</div><div>           actualOutputAB = runSP (arrA *** arrB) inputAB</div><div>

       in do putStrLn $ &quot;inputAB: &quot; ++ show inputAB</div><div>             putStrLn $ &quot;outputA: &quot; ++ show actualOutputA</div><div>             putStrLn $ &quot;outputA1: &quot; ++ show actualOutputA1</div>

<div>             putStrLn $ &quot;outputB: &quot; ++ show actualOutputB</div><div>             putStrLn $ &quot;outputB1: &quot; ++ show actualOutputB1</div><div>             putStrLn $ &quot;outputAB: &quot; ++ show actualOutputAB</div>

</div><div><br></div><div><br></div><div><br></div><div>[3]: <a href="https://github.com/peti/streamproc/blob/master/Control/Arrow/SP.hs#L58">https://github.com/peti/streamproc/blob/master/Control/Arrow/SP.hs#L58</a></div>

</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/10/7 Thiago Negri <span dir="ltr">&lt;<a href="mailto:evohunz@gmail.com" target="_blank">evohunz@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr">This is my first contact with QuickCheck, but does this test count as a proof that my implementation is correct?<div><br></div><div>QuickCheck shows 100 tests passed.</div><div><br></div><div><div>prop_a xs = runSP (f *** g) xs == runSP (first f &gt;&gt;&gt; swap &gt;&gt;&gt; first g &gt;&gt;&gt; swap) xs</div>


<div>  where swap = arr (\(a,b) -&gt; (b,a))</div><div>        f = arr (++&quot;a&quot;)</div><div>        g = arr (++&quot;b&quot;)</div></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra">

<br><br><div class="gmail_quote">
2013/10/7 Thiago Negri <span dir="ltr">&lt;<a href="mailto:evohunz@gmail.com" target="_blank">evohunz@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div dir="ltr"><div>&quot;<span style="font-family:arial,sans-serif;font-size:13px">On the one hand, indeterminate a&#39;s need to be fed in before indeterminate b&#39;s get pulled out. On the other hand, the c&#39;s need to behave as if they were in a no-op assembly line. One c goes in, the one (and same!) c drops out.&quot;</span><div>



<span style="font-family:arial,sans-serif;font-size:13px"><br></span></div></div><div><font face="arial, sans-serif">I agree with &quot;no-op assembly line&quot;, but when I&#39;m using `first` on a processor, I want to process the first stream *only*. The second stream should remain as it was not touched, so future processors will receive the same sequence from the second stream.</font></div>



<div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">I mean, I think I need to guarantee that this definition holds:</font></div><div><font face="arial, sans-serif"><br></font></div><div>



<font face="arial, sans-serif">`g *** f` is the same as `first g &gt;&gt;&gt; swap &gt;&gt;&gt; first f &gt;&gt;&gt; swap`</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">If my implementation of `first` uses a real no-op assembly line for `c` (i.e., `arr id`), then I would lose the stream. As you said, I need to buffer the second stream while processing the first one.</font></div>



<div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">Is my line of tought correct?</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">I&#39;ll try to write some tests to verify this.</font></div>



<div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">Thanks!</font></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/10/7 Kim-Ee Yeoh <span dir="ltr">&lt;<a href="mailto:ky3@atamo.com" target="_blank">ky3@atamo.com</a>&gt;</span><br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir="ltr"><div><div><div><div class="gmail_extra">Hey Thiago,<br><br>First of all, congratulations for reading Hughes! Many of his papers are worth reading and re-reading for both beginners and experts alike.<div>



<br><br><div class="gmail_quote">

On Tue, Oct 8, 2013 at 12:05 AM, Thiago Negri <span dir="ltr">&lt;<a href="mailto:evohunz@gmail.com" target="_blank">evohunz@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





Exercise 2 (section 2.5) is asking to create a Stream Processor that can map more than one output per input (e.g. 3 outcomes for a single consume of the stream).</blockquote></div><br></div>Given<div><br><br>&gt; data SP a b = Put b (SP a b) | Get (a -&gt; SP a b)<br>





<br></div></div><div>it&#39;s easy to see that it&#39;s not just about more than one output per input. It&#39;s about n pieces of input producing m pieces of output, where (n,m) may even -- and probably does -- depend on previous inputs!<br>





<br></div><div>The exercise asks for an implementation of the following Arrow instance:<br></div><div><br></div>&gt; first :: arr a b -&gt; arr (a,c) (b,c)<br><br></div>which, specialized to our case, is just SP a b -&gt; SP (a,c) (b,c).<br>





<br></div>It should now be apparent what the &#39;trickiness&#39; is. On the one hand, indeterminate a&#39;s need to be fed in before indeterminate b&#39;s get pulled out. On the other hand, the c&#39;s need to behave as if they were in a no-op assembly line. One c goes in, the one (and same!) c drops out.<br>





<br></div>So one way to look at this is as a buffering problem.<br><div><div><div><div><br>At this point, I&#39;d encourage you to think of some quickcheck tests you can write to convince yourself whether you have a right implementation or not.<br>





</div><div><br></div><div>Your main function doesn&#39;t seem adequate for the task.<span><font color="#888888"><br><br>-- Kim-Ee</font></span></div><div><div class="gmail_extra">
</div></div></div></div></div></div>
<br></div></div>_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>