<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <font size="-1"><font face="Helvetica, Arial, sans-serif">Hi Maks,<br>
        <br>
        Your typed identity function<br>
        <br>
        idLazyArray :: {a} -&gt; {a}<br>
        idLazyArray a = a<br>
        <br>
        is a smart way to solve the overloading for the array.<br>
        <br>
        Adding a type to a local definition always turns it into a
        function. This explains way adding a type to memo makes your
        program slow. You are completely right: the compiler should
        complain if it wants to treat a definition as a function while
        the user indicates with a =: that it should be a constant.<br>
        <br>
        In the future we will most likely add special notation to
        indicate strict or unboxed arrays. For situations like this it
        is also desirable to have syntax that indicates lazy arrays.<br>
        <br>
        In some situations it is desirable to be able to indicate the
        type of local constants. A Haskell like notation to indicate the
        type of expressions is a solution we are considering.<br>
        <br>
        Best, Pieter<br>
        <br>
      </font></font>
    <div class="moz-cite-prefix">On 22/08/2012 8:44 PM, Maks Verver
      wrote:<br>
    </div>
    <blockquote
      cite="mid:20120822204413.b4b7b2e788359346f383c69a@geocities.com"
      type="cite">
      <pre wrap="">On Tue, 21 Aug 2012 13:16:51 +0200
Pieter Koopman <a class="moz-txt-link-rfc2396E" href="mailto:pieter@cs.ru.nl">&lt;pieter@cs.ru.nl&gt;</a> wrote:
</pre>
      <blockquote type="cite">
        <pre wrap="">1) Most likely you have to recompile _SystemArray with the -ci flag 
(throw away the .o object file).
</pre>
      </blockquote>
      <pre wrap="">
That's it.  For future reference, I did this:

  make -C path-to-clean-dir CLMFLAGS+=-ci cleanup install


</pre>
      <blockquote type="cite">
        <pre wrap="">2) For instance
memoize :: ((Int -&gt; e) -&gt; (Int -&gt; e)) Int -&gt; (Int -&gt; e)
memoize f max = select (memo f max)
where
     memo :: ((Int -&gt; e) -&gt; (Int -&gt; e)) Int -&gt; {e}
     memo f max = array
     where array = { f (select array) i \\ i &lt;- [0..max] }
</pre>
      </blockquote>
      <pre wrap="">
I see.  That's a useful trick, though in this case you've reshuffled
the definitions considerably.

In this case I can also fix my problem by introducing a function to
restrict the kind of array used:

  lazyArray :: u:{a} -&gt; u:{a}
  lazyArray a = a

And then stay relatively close to the original, simpler definition:

  memoize :: ((Int -&gt; a) -&gt; Int -&gt; a) Int -&gt; (Int -&gt; a)
  memoize f max = g
      where g = select (lazyArray {f g i \\ i &lt;- [0..max]})

</pre>
      <blockquote type="cite">
        <pre wrap="">The standard solution is to add an argument to fix the the type.
</pre>
      </blockquote>
      <pre wrap="">
I can't imagine that's always a nice solution, considering that adding
an argument to a constant expression apparently affects the efficiency
of the resulting program.


</pre>
      <blockquote type="cite">
        <pre wrap="">3) It is essential to define the memo object as a local constant,
that is a definition without arguments. In that way it will become a
local graph which is shared in all compuations. Each local definition
with arguments is a function. Functions are lifted to the global
level by the compiler an evaluated for each argument all over again.
This is exactly what you try to avoid.
</pre>
      </blockquote>
      <pre wrap="">
This sounds reasonable but I still have trouble applying this to
concrete programs.  For example, it doesn't explain why this is fast,
even though I use a lambda-closure:

  memoize :: ((Int -&gt; Int) -&gt; Int -&gt; Int) Int -&gt; (Int -&gt; Int)
  memoize f max = g
      where
          g = \i -&gt; memo.[i]
          memo =: lazyArray { f g i \\ i &lt;- [0..max] }

... while adding a type to memo makes it slow:

  memoize :: ((Int -&gt; Int) -&gt; Int -&gt; Int) Int -&gt; (Int -&gt; Int)
  memoize f max = g
      where
          g = \i -&gt; memo.[i]
          memo :: {Int}  // &lt;-- only added this
          memo =: lazyArray { f g i \\ i &lt;- [0..max] }

What is the type inferred by the compiler in the first case that would
result in a completely different kind of evaluation?

Or does adding a type declaration turn `memo' from a graph into a
(constant) function?  In that case, shouldn't the compiler reject my
use of `=:' instead of `='?

 - Maks.
</pre>
    </blockquote>
    <br>
  </body>
</html>