Proc syntax in Haskell Arrows leads to severe performance penalty : <p>Using <code>proc</code> notation for <code>Arrow</code> seems to kill performance in my project. Here is a toy example of the problem:</p>

<p>We define Coroutine newtype (mostly copying from <a href="https://github.com/leonidas/codeblog/blob/master/2012/2012-01-08-streams-coroutines.md" rel="noreferrer" title="Generalizing Streams into Coroutines">Generalizing Streams into Coroutines</a>) to represent Mealy machines (i.e. functions that carry some state) with instances of <code>Category</code> and <code>Arrow</code>, write <code>scan</code> wrapper function and <code>evalList</code> runner function for lists.</p>

<p>Then we have <code>sumArr</code> and <code>sumArr'</code> functions where the latter is the former called within <code>proc</code> block.</p>

<p>Compiling with <code>stack ghc -- --make test.hs -O2</code> using ghc-8.0.2 on OS X I get runtime of 0.087 secs for <code>sumArr</code> and 3.263 secs for <code>sumArr'</code> (with a heavy memory footprint).</p>

<p>I would like to know if this in fact caused by using <code>proc</code> and if I can do something to have normal runtime behaviour when using <code>proc</code> notation (writing arrow code without it is painful). Thank you.</p>

<pre><code>{-# LANGUAGE Arrows #-}
{-# LANGUAGE BangPatterns #-}

import Prelude hiding (id, (.))
import Control.Arrow
import Control.Category
import qualified Data.List as L

newtype Coroutine i o = Coroutine { runC :: i -&gt; (o, Coroutine i o) }

instance Category Coroutine where
    id = Coroutine $ \i -&gt; (i, id)

    cof . cog = Coroutine $ \i -&gt;
        let (x, cog') = runC cog i
            (y, cof') = runC cof x
        in (y, cof' . cog')

instance Arrow Coroutine where
    arr f = Coroutine $ \i -&gt; (f i, arr f)

    first co = Coroutine $ \(a,b) -&gt;
        let (c, co') = runC co a in ((c,b), first co')

scan :: (o -&gt; t -&gt; o) -&gt; o -&gt; Coroutine t o
scan f = go where
    go i = Coroutine $ step i where
            step a b = let !a' = f a b in (a', go a')

evalList :: Coroutine a b -&gt; [a] -&gt; [b]
evalList a = L.map fst . L.drop 1 . L.scanl' (\(_, acc) v -&gt; let !x = runC acc v in x) (undefined, a)

sumArr, sumArr' :: Coroutine Int Int
sumArr = scan (\acc x -&gt; let !newAcc = acc + x in newAcc) 0
sumArr' = proc v -&gt; do sumArr -&lt; v

testData :: [Int]
testData = [1..1000000]

main = print $ L.last $ evalList sumArr' testData
</code></pre>
