<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Passing Curiosity: Posts tagged icfp</title>
    <link href="https://passingcuriosity.com/tags/icfp/icfp.xml" rel="self" />
    <link href="https://passingcuriosity.com" />
    <id>https://passingcuriosity.com/tags/icfp/icfp.xml</id>
    <author>
        <name>Thomas Sutton</name>
        
        <email>me@thomas-sutton.id.au</email>
        
    </author>
    <updated>2013-10-16T00:00:00Z</updated>
    <entry>
    <title>FP-Syd, October 2013</title>
    <link href="https://passingcuriosity.com/2013/fp-syd-october/" />
    <id>https://passingcuriosity.com/2013/fp-syd-october/</id>
    <published>2013-10-16T00:00:00Z</published>
    <updated>2013-10-16T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Little mention of <a href="http://linux.conf.au/">linux.conf.au 2014</a> and how we should all take a
look at the available programme and see if we want to go.</p>
<h2 id="eriks-icfp-roundup">Erik’s ICFP roundup</h2>
<p>The <a href="http://www.icfpconference.org">International Conference on Functional Programming</a> (ICFP for short) is
a three-day core conference and is collocated with a number of related events.
<a href="http://www.icfpconference.org/icfp2013/">ICFP 2013</a> was in Boston and a number of FP-Syd regulars presented and/or
attended.</p>
<p>Erik was a long time LCA attendee but ICFP has supplanted it as his “must go”
conference. I hope to make the same switch in <a href="http://www.icfpconference.org/icfp2014/">2014</a>!</p>
<p>The <strong>Haskell Implementers Workshop</strong> covers the internals of Haskell
implementations which, these days, means GHC to a very large extent. Covers a
lot of interesting techniques, with a particular focus on compilers. Erik
mentioned work on the non-safety of generalised <code>newtype</code> deriving; using
Hermit (a dynamic/guided optimisation framework) to optimise
scrap-your-boilerplate code; and Habit (a strict Haskell dialect for OS
programming).</p>
<p>The <strong>Commercial Users of Functional Programming</strong> was, reportedly, a bit
boring, but I’ve liked the few <a href="http://www.youtube.com/channel/UCfSUv7I_aHgzcnXMcd8obsw">CUFP 2013 YouTube videos</a> I’ve watched so
far. YMMV.</p>
<p>The <strong>Haskell Symposium</strong> was a main draw (for Erik). Highlights which Erik
found worth mentioning and I found worth noting down include:</p>
<ul>
<li><p>Oleg asked difficult questions of a lot of speakers. I wonder what would
happen if he asked an easy one?</p></li>
<li><p>Effects seemed something of a hot topic.</p></li>
<li><p>Demonstrations of <a href="http://hackage.haskell.org/package/liquidhaskell">Liquid Haskell</a> (which sounds pretty great), and a
Javascript backend for GHC.</p></li>
</ul>
<ul>
<li><p>Intel are developing a research compiler which uses GHC’s front-end to
compile to Core and then uses their own backend. Does loop vectorisation,
currently only better performance on a few benchmarks.</p></li>
<li><p>The third iteration of the I/O manager for GHC. Multithreaded, influenced by
Kazu Yamamoto’s work on Warp and mighttpd. Benchmarks against Nginx seem very
good; Warp with multiple cores sees extremely good speedups (contra Nginx).</p></li>
</ul>
<p>The main event – <strong>ICFP</strong> – is an academic conference and a lot of the
content will fly straight over the head of many a “working programmer”. Some of
the highlights included:</p>
<ul>
<li><p>A few talks on vectorisation (w/ SIMD from Intel, stream fusion, etc.) and
optimisation (for GPUs, etc.)</p></li>
<li><p>A few talks on dependent types.</p></li>
<li><p>Tactics in Coq are untyped; one talk discussed an approach to typed tactic
programming in Coq. Sounds especially interesting now that there is a “Coq
fight” in the FP-Syd calendar for next year!</p></li>
<li><p>People who didn’t attend are encourage to watch the video of the “fun with
semi-rings” talk. I haven’t been able to find it, though.</p></li>
<li><p>One talk described a useful-sounding approach to parsing context free
grammars with a divide-and-conquer approach, allowing partial and parallel
parsing.</p></li>
<li><p>Simon Peyton-Jones discussed the new curriculum for secondary computer
science education in the United Kingdom.</p></li>
<li><p>An extension or two to System F: System Fc (explicitly kind equality) and
System Fi (type indices). Everyone who can understand System F shouldn’t have
a problem reading the System Fi paper.)</p></li>
<li><p>Constrained monad problem (which, apparently, Oleg said was crap?). Paper on
solving a problem which occurs when using <code>Monad</code> but they should have used
<code>Applicative</code>. Seems as though they mostly wanted the <code>do</code> syntactic sugar;
see also idiom brackets and the attempt to generalise the Monad sugar.</p></li>
<li><p>“Querying ordered graphs.” Three words which sound interesting, but I’ve no
idea why I wrote them down.</p></li>
<li><p>Also: experience reports! Someone took a Scheme compiler from 4-5 to 25
passes (“nanoparsing”?) and, at the same time, also added a good colouring
register allocator. Apparently one of these changes made it better.</p></li>
</ul>
<p>Other events:</p>
<ul>
<li><p>Talking about a benchmark/framework to compare approaches to generic
programming at the Workshop on Generic Programming.</p></li>
<li><p>Brent Yorgey doing animations with <code>diagrams</code> at the Workshop on Functional
Art, Music, Modeling and Design.</p></li>
<li><p>Chordify is a system (written in Haskell) to analyse recordings and generate
chord transcripts. It’s not perfect but gives pretty good approximations.</p></li>
</ul>
<h2 id="ben-talking-about-data-flow-fusion">Ben talking about Data Flow Fusion</h2>
<p><a href="http://www.cse.unsw.edu.au/~benl/">Ben Lippmeier</a> – an FP-Syd regular – presented a paper at ICFP and
reprised that presentation back in Sydney for those of use who weren’t in
Boston. He described an approach using data flow to guide the compilation of
programs using stream fusion.</p>
<p>Wants to process a list of points, adding 1 to each, filtering those about 0
and also finding the maximum.</p>
<p>Doing stream fusion</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">map</span> f <span class="ot">=</span> unstream <span class="op">.</span> mapsS f <span class="op">.</span> stream</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">filter</span> f <span class="ot">=</span> unstream <span class="op">.</span> filterS f <span class="op">.</span> stream</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- RULE to remove (stream . unstream)</span></span></code></pre></div>
<p>Example computes <code>(vec3, n)</code> can’t float <code>vec3</code> because it’s being used in the
result <em>and</em> in the computation of <code>n</code>. So we get two loops.</p>
<pre><code>**1** -&gt; 2 -&gt; **3** -&gt; 4
	              |      |
              (    ,    )</code></pre>
<p><code>zipWithX</code> tends to use X+1 loop counters for stream fusion. There’re only 8
registeres to use on some platforms.</p>
<h3 id="data-flow-fusion">Data Flow Fusion</h3>
<h4 id="slight-manual-refactor">Slight manual refactor</h4>
<p>Split <code>filter</code> into two combinators <code>flag</code> – which contains <code>True</code> or <code>False</code>
for each member – and <code>pack</code> – which does the filtering.</p>
<h4 id="extract-the-data-flow-graph">Extract the data flow graph</h4>
<p>This code generates the data flow graph.</p>
<pre><code>fun vec1 (\s1 -&gt; 
  let s2    = map (+ 1) s1
      flags = map (&gt; 0) s2
  in mkSel flags (\sel -&gt;
  let s3   = pack sel s2
      vec3 = create s3
      n    = fold max 0 s3
  in (vec3, n)))

vec1 :: Vector Int
s1 :: Series k1 Int
s2 :: Series k1 Int
flags :: Sel k1 k2
s3 :: Series k2 Int</code></pre>
<p>Series has a phantom type variable which helps keep track of the code which can
be fused into a single loop.</p>
<p>We learn that <code>k1 &gt;= k2</code></p>
<p>With the flow graph (annotated with operations, etc.), throw away the source.</p>
<h4 id="schedule-the-grapch-into-an-abstract-loop-nest">Schedule the grapch into an abstract loop nest</h4>
<p>Abstract loop nest:</p>
<pre><code>loop k1 {

  start: ....
  
  body: ....
  
  inner: ...
  
  end: ...

} yields ...</code></pre>
<p>Start at the front of the data flow graph and add elements of the graph to the
nested abstract loop.</p>
<p>Operations go into different places in the nested abstract loop. A <code>fold</code>, for
example, allocates and accumulator in <code>start</code>, increments somewhere within
<code>body</code> and reads it in <code>end</code>.</p>
<h4 id="extract-implementation-from-abstract-loop-nest.">Extract implementation from abstract loop nest.</h4>
<p>Translate the various bits and pieces of the abstract loop nest data structure
into different Haskell combinators.</p>
<h3 id="implementation">Implementation</h3>
<p>GHC plugin which grabs Core, does data flow compilation and generates Core to
give back to GHC.</p>
<p>Some issues in current implementation where LLVM doesn’t realise that writing
to the output doesn’t <em>need</em> to reload the start and length numbers.</p>
<blockquote>
<p><strong>If</strong> your program is first order (argument functions take scalars,
not series), non-recursive, synchronous, finite data flow program
using out combinators.</p>
<p><strong>Then</strong> by construction your program will be compiled correctly by
this system.</p>
</blockquote>
<h2 id="liam-on-cdsl">Liam on CDSL</h2>
<p>Liam O’Connor works for NICTA. Instead of talking about something he recently
learned, he’s talking about work: CDSL - a restricted functional language for
file system verification.</p>
<p>Trying to establish a formal proof of the correctness of a file system driver
in an operating system.</p>
<p>Already have an architecture for this sort of problem (from seL4):</p>
<ol type="1">
<li><p>Abstract spec - high-level, nondeterministic (followed by an “interesting”
proof of relation to ~ 15%)</p></li>
<li><p>Low level spec - purely functional (followed by a “largely boring” proof of
relation to ~ 30%)</p></li>
<li><p>C implementation - efficient.</p></li>
</ol>
<p>~ 55% is showing that the other proofs don’t do something stupid; proving
invariants all hold.</p>
<p>Ignoring the kernel proper, architecture support, and drivers (another NICTA
project), the largest part of the Linux kernel is the <code>fs/</code> directory; 31
different file systems were supported by the kernel running on some random
NICTA server.</p>
<p>There are lots of file systems with, one assumes, quite a lot of common
functionality and infrastructure. The goal of the project is not to make a
cathedral of a single verified file system, more a factory for churning out
numerous file systems. The approach is to use a DSL to generate the low-level
spec, proof and implementation. High-level spec and proof are done by hand, so
generated outputs need to be readable.</p>
<p>Should</p>
<ul>
<li><p>establish key verification properties</p></li>
<li><p>compete with efficient C code (imperative, destructive updates, etc.)</p></li>
<li><p>be expressive enough to write a file system</p></li>
</ul>
<p>But:</p>
<ul>
<li>doesn’t need to express <em>everything</em> in a file system. Hand-written components
could be plugged in to the DSL (and, hopefully, re-used).</li>
</ul>
<h3 id="simply-typed-lambda-calculus">Simply-typed lambda calculus</h3>
<p>Simple-typed lambda calculus is strongly normalising (you can’t write general
recursion, e.g. the Y combinator).</p>
<p>First-order language: lambdas go away, use <code>let</code> binding and restrict to
defining top-level functions. Added structural rules for mixing, weakening, ?</p>
<p>Need to do memory management which is safe, expressive (no pass by value, we
need the heap), no GC (you’d have to verify it, introduce latency, etc.)</p>
<p>Automatic member management (GC) is too big a burden. Many static automatic
memory management is inefficient or unsafe.</p>
<p>What about manual memory management?</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> x <span class="ot">=</span> allocateData ()</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    x' <span class="ot">=</span> updateData x</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">=</span> free x</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">in</span> x'</span></code></pre></div>
<p>But this is terrible! Unsafe, inefficient, etc.</p>
<p>So have a linear type system, throwing away weakening, etc. Forces use of
things exactly matching (can’t alloc and not use, doesn’t discharge the new
fact). The typing rules require that introduction and elemination be paired.</p>
<p>Linear types means that the elimination operations (e.g. <code>updateDate</code>) are the
<em>last</em> to access terms, so they can do destructive updates.</p>
<p>Two interpresations of these semantics:</p>
<ul>
<li><p>value semantics: pass by value, no heap, immutability, reasoning.</p></li>
<li><p>update semantics: heap, updates, deallocates, implementation.</p></li>
</ul>
<p>Linear types allow for both.</p>
<p>But sometimes you want non-linear, pass-by-value (arithmetic operations, etc.):</p>
<ul>
<li>Unboxed types, ints, small structs</li>
<li>Functions themselves</li>
</ul>
<p>Allow structural rules (dereliction and contraction) for certain types only. So
now we have <code>T_{.}</code> and <code>T_{#}</code> (unboxed and value types).</p>
<h3 id="buffer-interface">Buffer interface</h3>
<pre><code>make : () -&gt; .Buf
free : .Buf -&gt; ()
length : .Buf -&gt; (#U32, .Buf)

serialise : (.Obj, .Buf) -&gt; (.Obj, .Buf)
deserialise : .Buf -&gt; (.Obj, .Buf)</code></pre>
<p>Non-linear “look but don’t touch” references with <code>*</code>:</p>
<pre><code>make : () -&gt; .Buf
free : .Buf -&gt; ()

length : *Buf -&gt; #U32
serialise : (*Obj, .Buf) -&gt; .Buf
deserialise : *Buf -&gt; .Obj</code></pre>
<p>Use <code>let!</code> construct which is like <code>let</code> but we mark specific variables as
read-only within the <code>let</code> clauses and back to linear in the <code>in</code>.</p>
<p>But this is unsafe (read-only can escape the let). Could use regions, but
choose not to unless it’s required.</p>
<p>Linear typing breaks some control flow:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> x <span class="ot">=</span> alloc ()</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">in</span> <span class="kw">if</span> cond</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>   <span class="kw">then</span> update(x)</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>   <span class="kw">else</span> x</span></code></pre></div>
<h3 id="loops">Loops</h3>
<p>Hardest, most annoying part of the formalisation of the language.</p>
<p>Built-in loop combinators, map, fold, with, for.</p>
<pre><code>let sum = for (x,y) in fold(arr) with 0
              do (x + y)

let arr', sum = for (x,y) in map(arr) with 0
                    do (x * 2, x + y)</code></pre>
<p>Alas, this is unsafe. Double free, etc. But you can restrict linear types in
the loop expression. Then have to make any required linear types into
accumulator parms.</p>
<h3 id="error-handling">Error handling</h3>
<p>The return-code convention using in languages like C is pretty bad. Instead,
separate statements and expressions.</p>
<p>Statements have three types:</p>
<ul>
<li>s : <span class="math inline">\({\bar T_{s}}\)</span></li>
<li>s : <span class="math inline">\(fails {\bar T_{f}}\)</span></li>
<li>s : <span class="math inline">\({\bar T_{?}} fails {\bar T_{?}}\)</span></li>
</ul>
<p>Type of <code>if then else</code> is <code>T_{t} \leastupperbound T_{e}</code>. Lattice join,
subtype, etc.</p>
<p>Make <code>let</code> and <code>let!</code> only handle success cases. Force sub-expressions to
handle potential errors. Type system <em>forces</em> you to handle your errors and the
<em>linear</em> type system forces you to free your resources.</p>
<h3 id="types">Types</h3>
<p>Product and sum types (implemented as structs and tagged unions).</p>
<p>Accessing members of linear records is problematic as you use the record
multiple times:</p>
<pre><code>let sum = operation(x.field1, x.field2)</code></pre>
<p>Instead use an open/close structure.</p>]]></summary>
</entry>

</feed>
