tag:blogger.com,1999:blog-25538159236406205722024-02-19T07:24:25.216-05:00FlygdynamikernBjörn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-2553815923640620572.post-74090964975497837672014-09-12T08:46:00.000-04:002014-09-12T08:46:41.935-04:00Haskell tools for satellite operations<div dir="ltr" style="text-align: left;" trbidi="on">
At last week's CUFP I did a talk called “Haskell tools for satellite operations”. The abstract is:<div>
<br /></div>
<div>
<blockquote class="tr_bq">
<div style="background-color: white; box-sizing: border-box; color: #444444; font-family: Lato, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.6; margin-bottom: 1.25rem; padding: 0px; text-rendering: optimizelegibility;">
Since 2013-04 the presenter has been supporting SSC (the Swedish Space Corporation) in operating the telecommunications satellite “Sirius 3” from its Mission Control Center in Kiruna. Functions in the satellite vendor's operations software are breaking down as the orbit of the ageing satellite degrades. To fill in the gaps in software capabilities the presenter has developed several operational tools using Haskell.</div>
<div style="background-color: white; box-sizing: border-box; color: #444444; font-family: Lato, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.6; margin-bottom: 1.25rem; padding: 0px; text-rendering: optimizelegibility;">
The talk will give an overview of the satellite operations environment, the tools developed in Haskell, how they benefitted (and occasionally suffered) from the choice of implementation language, which (public) libraries were critical to their success, and how they were deployed in the satellite operations environment.</div>
</blockquote>
A video recording of the talk is available on the <a href="http://cufp.org/2014/bjrn-buckwalter-haskell-tools-for-satellite-operations.html">CUFP page</a> for the talk and on <a href="https://www.youtube.com/watch?v=QpRGe5d3ouo">youtube</a>.<br />
<div>
<br /></div>
</div>
<div>
If this interests you be sure to check out the other talk from the “Functional programming in space!” track; Michael Oswald's <a href="http://cufp.org/2014/michael-oswald-haskell-in-the-misson-control-domain.html">Haskell in the Misson Control Domain</a>.</div>
</div>
Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-24703181602891627652014-02-11T08:03:00.000-05:002014-02-11T08:03:01.039-05:00Numtype(-tf) and dimensional(-tf) updated for GHC 7.8.1<p>My <a href="http://hackage.haskell.org/package/numtype"><em>numtype</em></a> and <a href="http://hackage.haskell.org/package/numtype-tf"><em>numtype-tf</em></a> libraries both needed one line changes to be compatible with the GHC 7.8.1 release candidate. Versions 1.1 and 0.1.2 (respectively) have been uploaded to hackage.</p>
<p>The update to numtype also necessitated an update to <a href="http://hackage.haskell.org/package/dimensional"><em>dimensional</em></a>, mainly to bump the upper bounds of the numtype dependency, but a few API additions snuck in too. The change log for the new version (0.12.3), as well as the other versions that have been uploaded to hackage since my <a href="http://flygdynamikern.blogspot.se/2011/05/announce-dimensional-010.html">previous version announcement</a> can be found at the bottom of this post.</p>
<p><a href="http://hackage.haskell.org/package/dimensional-tf"><em>Dimensional-tf</em></a> didn’t need an update for GHC 7.8 but has been updated with the same API additions as dimensional.</p>
<h1 id="dimensionals-changelog">Dimensional’s changelog</h1>
<h2 id="section">0.13 (2014-02)</h2>
<ul>
<li>Bump numtype dependency to 1.1 (GHC 7.8.1 compatibility fix).</li>
<li>Added <code>Torque</code>.</li>
<li>Added D.. for the type synonym quantities (e.g., <code>Angle</code>).</li>
</ul>
<h2 id="section-1">0.12.2 (2013-11)</h2>
<ul>
<li>Added <code>FirstMassMoment</code>, <code>MomentOfInertia</code>, <code>AngularMomentum</code>.</li>
<li>Improved unit numerics.</li>
</ul>
<h2 id="section-2">0.12.1 (2013-07)</h2>
<ul>
<li>Typeable Dimensionals.</li>
</ul>
<h2 id="section-3">0.12 (2013-06)</h2>
<ul>
<li>Polymorphic <code>_0</code> (closes issue 39).</li>
<li>Added <code>astronomicalUnit</code>.</li>
<li>Added imperial volume units.</li>
<li>Added ‘mil’ (=inch/1000).</li>
<li>Added <a href="http://tauday.com/tau-manifesto"><code>tau</code></a>.</li>
<li>Added <code>KinematicViscosity</code>.</li>
</ul>
<h2 id="section-4">0.10.1.2 (2011-09)</h2>
<ul>
<li>Bumped time dependency to < 1.5.</li>
</ul>
<h2 id="section-5">0.10.1.2 (2011-08)</h2>
<ul>
<li>Bumped time dependency to < 1.4.</li>
</ul>
<h2 id="section-6">0.10.1 (2011-08)</h2>
<p>GHC 7.2.1 compatibility fix:</p>
<ul>
<li>Increased CGS context-stack to 30.</li>
</ul>
Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-29797092223273081132014-02-09T12:39:00.001-05:002014-02-11T08:04:54.989-05:00Joy and caution with -XNegativeLiterals in GHC 7.8<p>The new <a href="http://www.haskell.org/ghc/docs/7.8.1-rc1/html/users_guide/syntax-extns.html#negative-literals">NegativeLiterals</a> extension in <a href="http://www.well-typed.com/blog/85">GHC 7.8</a> scratches an itch I have had for a long time. Namely:</p>
<pre class="sourceCode literate literatehaskell"><code class="sourceCode literatehaskell"><span class="ot">></span> y <span class="fu">=</span> (<span class="fu">-</span><span class="dv">41940</span><span class="fu">.</span><span class="dv">917505092</span>) <span class="fu">*~</span> kilo meter</code></pre>
<p>With NegativeLiterals users of <a href="http://dimensional.googlecode.com">dimensional</a> can finally write:</p>
<pre class="sourceCode literate literatehaskell"><code class="sourceCode literatehaskell"><span class="ot">></span> y <span class="fu">=</span> <span class="fu">-</span><span class="dv">41940</span><span class="fu">.</span><span class="dv">917505092</span> <span class="fu">*~</span> kilo meter</code></pre>
<p>Thanks GHC HQ and contributors!</p>
<p>However, be careful so the extension doesn’t break your calculations. Here is an example (not using dimensional) of how you could get bitten. Without NegativeLiterals:</p>
<pre class="sourceCode literate literatehaskell"><code class="sourceCode literatehaskell"><span class="ot">></span> <span class="dt">Prelude</span><span class="fu">></span> <span class="fu">-</span><span class="dv">2</span> <span class="fu">^</span> <span class="dv">2</span>
<span class="ot">></span> <span class="fu">-</span><span class="dv">4</span></code></pre>
<p>With NegativeLiterals:</p>
<pre class="sourceCode literate literatehaskell"><code class="sourceCode literatehaskell"><span class="ot">></span> <span class="dt">Prelude</span><span class="fu">></span> <span class="fu">-</span><span class="dv">2</span> <span class="fu">^</span> <span class="dv">2</span>
<span class="ot">></span> <span class="dv">4</span></code></pre>
<p>I certainly prefer the latter behaviour, but having some regression tests in place when enabling NegativeLiterals might be a good idea.</p>
Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com6tag:blogger.com,1999:blog-2553815923640620572.post-26966224039451090862012-02-12T02:52:00.004-05:002012-02-14T20:26:17.660-05:00ANNOUNCE: dimensional-tf-0.10 – Statically checked physical dimensions with type families<p>As promised when I released <em><a href="http://hackage.haskell.org/package/numtype-tf">numtype-tf</a></em> in January I have now also created the <em><a href="http://hackage.haskell.org/package/dimensional-tf">dimensional-tf</a></em> library – a conversion of the <em><a href="http://dimensional.googlecode.com">dimensional</a></em> library to use <a href="http://www.haskell.org/haskellwiki/GHC/Type_families"><em>Type Families</em></a> instead of <a href="http://www.haskell.org/haskellwiki/Functional_dependencies"><em>Functional Dependencies</em></a>.</p><p>I skipped the experimental and to my knowledge unused <code>CGS</code> and <code>Extensible</code> modules. If you would like to see them ported let me know.</p><p>For straight-forward usage, e.g. the <a href="http://code.google.com/p/dimensional/w/list?q=label:Example">examples</a> on the dimensional wiki, the only change required from library users to switch from dimensional to dimensional-tf is inserting <code>.TF</code> in the import statements. E.g.:</p><pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.TF.Prelude</span>
<span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.TF.NonSI</span></code></pre><p>In such cases the choice of using dimensional backed by functional dependencies or type families is largely philosophical as neither will be visible in the client code.</p><p>If you do more advanced things with polymorphic dimensions and explicit type signatures you will have to convert the type signatures from MLTC style constraints to type families. E.g.:</p><pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">myFunc </span><span class="ot">::</span> (<span class="kw">Num</span> a, <span class="dt">Mul</span> d1 d2 d3) <span class="ot">=></span> <span class="dt">Quantity</span> d1 a <span class="ot">-></span> <span class="dt">Quantity</span> d2 a <span class="ot">-></span> <span class="dt">Quantity</span> d3 a</code></pre><p>would change to:</p><pre class="sourceCode"><code class="sourceCode haskell"><span class="ot">myFunc </span><span class="ot">::</span> <span class="kw">Num</span> a <span class="ot">=></span> <span class="dt">Quantity</span> d1 a <span class="ot">-></span> <span class="dt">Quantity</span> d2 a <span class="ot">-></span> <span class="dt">Quantity</span> (<span class="dt">Mul</span> d1 d2) a</code></pre><p>Compiler errors will also be different in dimensional-tf, for better or for worse.</p><p>So, should you use dimensional or dimensional-tf? For the time being I consider dimensional-tf to be experimental. If you want stability stick with dimensional for now. If your dislike of functional dependencies trumps your need for stability, then try dimensional-tf. If dimensional-tf eventually proves itself to be a better dimensional I will merge it into the latter with a major version bump.</p><p>Dimensional-tf-0.1 compiles on GHC-7.0. The source code is on <a href="https://github.com/bjornbm/dimensional-tf">Github</a>.</p><p><strong>Update 2012-02-15:</strong> In case this wasn't building for you on GHC-7.4.1; I've <a href="http://hdiff.luite.com/cgit/dimensional-tf/commit?id=0.1.0.1">added a FlexibleInstances pragma</a> that should take care of it. Dimensional-tf-0.1.0.1 compiles on GHC-7.0 and 7.4.</p><a href="http://flattr.com/thing/499213/ANNOUNCE-dimensional-tf-0-10-Statically-checked-physical-dimensions-with-type-families" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-58950239299822871992012-01-25T08:36:00.001-05:002012-01-25T08:44:59.022-05:00Type level integers with Type Families (numtype-tf 0.1)<p>Pretty much since they were introduced into GHC I’ve been meaning to try to port the <em><a href="http://dimensional.googlecode.com">dimensional</a></em> library to use <a href="http://www.haskell.org/haskellwiki/GHC/Type_families"><em>Type Families</em></a> instead of <a href="http://www.haskell.org/haskellwiki/Functional_dependencies"><em>Functional Dependencies</em></a>. However, functional dependencies have served me quite well and I’ve been lacking the inspiration to dig into type families. That is, until I read the Leonidas’ <a href="https://github.com/leonidas/codeblog/blob/master/2011/2011-12-21-static-vector-algebra.md"><em>Statically Typed Vector Algebra Using Type Families</em></a>. Leonidas’ blog post resonated with me as the problem it addresses is related to one I myself have been interested in for some time (<a href="http://stackoverflow.com/questions/5850392/can-good-type-systems-distinguish-between-matrices-in-different-bases/5856996#5856996">linear algebra with static guarantees</a>). It also gave me a clear vision of how to apply type families to the fundamendal problem of dimensional – type level integers.</p><p>I’ve implemented the <em><a href="http://hackage.haskell.org/package/numtype-tf">numtype-tf</a></em> library which is in essence <em><a href="http://hackage.haskell.org/package/numtype">numtype</a></em> using type families (hence the “-tf”) instead of functional dependencies. Some of my design decisions are slightly different (beside the choice of type system extension), e.g. the representation of negative integers is different and the <code>PosType</code> and <code>NegType</code> classes have been dropped in numtype-tf. The haddocks have also been improved a little.</p><p>A feature of the functionally dependent numtype that I was unable to reproduce with type families is ”<a href="http://www.haskell.org/pipermail/haskell-prime/2011-June/003438.html">mutual dependencies</a>”, used in the <code>Sum</code> and <code>Div</code> type classes of numtype. Here is an example of type signatures (instances omitted) and ghci usage:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">class</span> <span class="dt">Sum</span> a b c <span class="fu">|</span> a b <span class="ot">-></span> c, a c <span class="ot">-></span> b, b c <span class="ot">-></span> a<br />> <span class="ot">(+) </span><span class="ot">::</span> (<span class="dt">Sum</span> a b c) <span class="ot">=></span> a <span class="ot">-></span> b <span class="ot">-></span> c<br />> <span class="ot">(-) </span><span class="ot">::</span> (<span class="dt">Sum</span> a b c) <span class="ot">=></span> c <span class="ot">-></span> b <span class="ot">-></span> a</code></pre><pre><code>\*Numeric.NumType> pos3 - pos5
NumType -2
</code></pre><p>To the best of my knowledge corresponding code with type families would be along the lines of:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">type</span> family <span class="dt">Sum</span> a b<br />> <span class="ot">(+) </span><span class="ot">::</span> a <span class="ot">-></span> b <span class="ot">-></span> <span class="dt">Sum</span> a b<br />> <span class="ot">(-) </span><span class="ot">::</span> <span class="dt">Sum</span> a b <span class="ot">-></span> b <span class="ot">-></span> a</code></pre><pre><code>\*Numeric.NumType.TF> pos3 - pos5
<interactive>:1:1:
Couldn't match type `Sum a0 Pos5' with `S Pos2'
…
</code></pre><p>In order for the latter to compute we must assist the type checker by being explicit about the type of <code>a0</code>, i.e. <code>pos3 - pos5 :: Neg2</code>, which largely defeats the purpose of type level arithmetic. Instead two type families are used in numtype-tf:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">type</span> family <span class="dt">Add</span> a b <span class="co">-- a + b</span><br />> <span class="ot">(+) </span><span class="ot">::</span> a <span class="ot">-></span> b <span class="ot">-></span> <span class="dt">Add</span> a b<br />> <span class="kw">type</span> family <span class="dt">Sub</span> a b <span class="co">-- a - b.</span><br />> <span class="ot">(-) </span><span class="ot">::</span> a <span class="ot">-></span> b <span class="ot">-></span> <span class="dt">Sub</span> a b</code></pre><p>This works OK but the lack och mutual dependencies in type families restricts what I will losely refer to as “type inference back tracking”. This may or may not be a significant drawback compared to fundep numtype depending on the use case.</p><p>If you are interested in comparing code written with type families to code written with functional dependencies take a look at the respective modules on Github: <a href="https://github.com/bjornbm/numtype-tf/blob/master/Numeric/NumType/TF.lhs">Numeric.NumType.TF</a> vs. <a href="https://github.com/bjornbm/numtype/blob/master/Numeric/NumType.lhs">Numeric.NumType</a>.</p><p>The next step is to reimplement dimensional as <em>dimensional-tf</em> in order to exercise numtype-tf and better understand the impact of the differences with respect to numtype. I am also looking forward to playing with <a href="http://hackage.haskell.org/trac/ghc/wiki/TypeNats">GHC.TypeNats</a> in GHC 7.4.</p><a href="http://flattr.com/thing/470789/Type-level-integers-with-Type-Families-numtype-tf-0-1" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com2tag:blogger.com,1999:blog-2553815923640620572.post-70269407065845007182011-09-15T11:08:00.001-04:002011-09-15T11:26:52.407-04:00Yesod Cookbook: Internationalized FormI posted the following example of an internationalized form to the <a href="http://www.yesodweb.com/wiki/Cookbook"><i>Yesod Cookbook</i></a> a few days ago. <a href="http://www.yesodweb.com/">Yesod</a> has a pretty awesome library for programming with <a href="http://www.yesodweb.com/book/forms">forms</a> and also a flexible but currently under-documented system for <a href="http://www.yesodweb.com/show/topic/475">internationalization</a>. However, how the two interact, while straightforward, might not be immediately obvious to the newcomer. Hence the motivation for the below example which shows how to internationalize both custom messages and Yesod's built-in <code>FormMessage</code>s (mostly form error messages).<br />
<br />
Familiarity with Yesod at the level of the <a href="http://www.yesodweb.com/book"><i>Yesod Book</i></a> is assumed.<br />
<br />
<table><tr><td style="text-align:right;border-right: 1px solid gray;padding: 0 5px 0 5px;vertical-align: baseline;"><pre style="padding: 0;margin: 0;"><a id="1">1
</a><a id="2">2
</a><a id="3">3
</a><a id="4">4
</a><a id="5">5
</a><a id="6">6
</a><a id="7">7
</a><a id="8">8
</a><a id="9">9
</a><a id="10">10
</a><a id="11">11
</a><a id="12">12
</a><a id="13">13
</a><a id="14">14
</a><a id="15">15
</a><a id="16">16
</a><a id="17">17
</a><a id="18">18
</a><a id="19">19
</a><a id="20">20
</a><a id="21">21
</a><a id="22">22
</a><a id="23">23
</a><a id="24">24
</a><a id="25">25
</a><a id="26">26
</a><a id="27">27
</a><a id="28">28
</a><a id="29">29
</a><a id="30">30
</a><a id="31">31
</a><a id="32">32
</a><a id="33">33
</a><a id="34">34
</a><a id="35">35
</a><a id="36">36
</a><a id="37">37
</a><a id="38">38
</a><a id="39">39
</a><a id="40">40
</a><a id="41">41
</a><a id="42">42
</a><a id="43">43
</a><a id="44">44
</a><a id="45">45
</a><a id="46">46
</a><a id="47">47
</a><a id="48">48
</a><a id="49">49
</a><a id="50">50
</a><a id="51">51
</a><a id="52">52
</a><a id="53">53
</a><a id="54">54
</a><a id="55">55
</a><a id="56">56
</a><a id="57">57
</a><a id="58">58
</a><a id="59">59
</a><a id="60">60
</a><a id="61">61
</a><a id="62">62
</a><a id="63">63
</a><a id="64">64
</a><a id="65">65
</a><a id="66">66
</a><a id="67">67
</a><a id="68">68
</a><a id="69">69
</a><a id="70">70
</a><a id="71">71
</a><a id="72">72
</a><a id="73">73
</a><a id="74">74
</a><a id="75">75
</a><a id="76">76
</a><a id="77">77
</a><a id="78">78
</a><a id="79">79
</a><a id="80">80
</a><a id="81">81
</a><a id="82">82
</a><a id="83">83
</a><a id="84">84
</a><a id="85">85
</a><a id="86">86
</a><a id="87">87
</a><a id="88">88
</a><a id="89">89
</a><a id="90">90
</a><a id="91">91
</a><a id="92">92
</a><a id="93">93
</a><a id="94">94
</a><a id="95">95
</a><a id="96">96
</a><a id="97">97
</a><a id="98">98
</a><a id="99">99
</a><a id="100">100
</a><a id="101">101
</a><a id="102">102
</a><a id="103">103
</a><a id="104">104
</a><a id="105">105
</a><a id="106">106
</a><a id="107">107
</a><a id="108">108
</a><a id="109">109
</a><a id="110">110
</a><a id="111">111
</a><a id="112">112
</a><a id="113">113
</a><a id="114">114
</a></pre></td><td style="padding: 0 5px 0 5px;"><pre style="padding: 0;margin: 0;"><span style="color: gray;">{-</span>
<span style="color: gray;">INTERNATIONALIZED FORM</span>
<span style="color: gray;">Below is an example of how to internationalize a Yesod application,</span>
<span style="color: gray;">including internationalization (i18n) of a form and Yesod's built-in</span>
<span style="color: gray;">form error messages.</span>
<span style="color: gray;">In the example we create a simple site that will show messages in</span>
<span style="color: gray;">Swedish or English depending on the browser's preferred language.</span>
<span style="color: gray;">If neither Swedish or English are preferred languages the site will</span>
<span style="color: gray;">default to Swedish.</span>
<span style="color: gray;">Familiarity with Yesod at the level of the Yesod book is assumed,</span>
<span style="color: gray;">comments are concentrated to the parts relevant to i18n.</span>
<span style="color: gray;">-}</span>
<span style="color: gray;">{-# LANGUAGE QuasiQuotes</span>
<span style="color: gray;"> , TemplateHaskell</span>
<span style="color: gray;"> , MultiParamTypeClasses</span>
<span style="color: gray;"> , OverloadedStrings</span>
<span style="color: gray;"> , TypeFamilies</span>
<span style="color: gray;"> #-}</span>
<span style="color: green;font-weight: bold;">import</span> <span style="color: blue;">Yesod</span>
<span style="color: green;font-weight: bold;">import</span> <span style="color: blue;">Yesod.Form.I18n.Swedish</span>
<span style="color: green;font-weight: bold;">import</span> <span style="color: blue;">Control.Applicative</span> ((<$>), (<*>))
<span style="color: green;font-weight: bold;">import</span> <span style="color: blue;">Data.Text</span> (<span style="color: blue;">Text</span>)
<span style="color: gray;">-- Our foundation data type.</span>
<span style="color: green;font-weight: bold;">data</span> <span style="color: blue;">MyApp</span> = <span style="color: blue;">MyApp</span>
<span style="color: blue;font-weight: bold;">mkYesod</span> <span style="color: green;">"MyApp"</span> [parseRoutes|
/ <span style="color: blue;">RootR</span> <span style="color: blue;">GET</span>
|]
<span style="color: green;font-weight: bold;">instance</span> <span style="color: blue;">Yesod</span> <span style="color: blue;">MyApp</span> <span style="color: green;font-weight: bold;">where</span>
approot _ = <span style="color: green;">""</span>
<span style="color: gray;">-- Here we provide internationalization of Yesod's built in form</span>
<span style="color: gray;">-- messages (mostly error messages). For brevity it is assumed that</span>
<span style="color: gray;">-- Swedish translations are exported as 'swedishFormMessage' by the</span>
<span style="color: gray;">-- module Yesod.Form.I18n.Swedish (an implementation can be copied</span>
<span style="color: gray;">-- from <a href="https://gist.github.com/1209328">https://gist.github.com/1209328</a>).</span>
<span style="color: green;font-weight: bold;">instance</span> <span style="color: blue;">RenderMessage</span> <span style="color: blue;">MyApp</span> <span style="color: blue;">FormMessage</span> <span style="color: green;font-weight: bold;">where</span>
renderMessage _ [] = swedishFormMessage <span style="color: gray;">-- Default to Swedish</span>
renderMessage _ (<span style="color: green;">"sv"</span>:ls) = swedishFormMessage
renderMessage _ (<span style="color: green;">"en"</span>:ls) = defaultFormMessage <span style="color: gray;">-- English</span>
renderMessage m (_ :ls) = renderMessage m ls
<span style="color: gray;">-- Next we define the custom messages present on the site and their</span>
<span style="color: gray;">-- rendering functions for different languages.</span>
<span style="color: green;font-weight: bold;">data</span> <span style="color: blue;">Msg</span> = <span style="color: blue;">Model</span>
| <span style="color: blue;">Year</span>
| <span style="color: blue;">Please</span>
<span style="color: gray;">-- Rendering function for English.</span>
<span style="color: blue;font-weight: bold;">renderEnglish</span> <span style="color: blue;">Model</span> = <span style="color: green;">"Model"</span>
<span style="color: blue;font-weight: bold;">renderEnglish</span> <span style="color: blue;">Year</span> = <span style="color: green;">"Year"</span>
<span style="color: blue;font-weight: bold;">renderEnglish</span> <span style="color: blue;">Please</span> = <span style="color: green;">"Please fill in your car's details"</span>
<span style="color: gray;">-- Rendering function for Swedish.</span>
<span style="color: blue;font-weight: bold;">renderSwedish</span> <span style="color: blue;">Model</span> = <span style="color: green;">"Modell"</span>
<span style="color: blue;font-weight: bold;">renderSwedish</span> <span style="color: blue;">Year</span> = <span style="color: green;">"Årgång"</span>
<span style="color: blue;font-weight: bold;">renderSwedish</span> <span style="color: blue;">Please</span> = <span style="color: green;">"Vänligen fyll i uppgifterna för din bil"</span>
<span style="color: gray;">-- The instance used to select the appropriate rendering function.</span>
<span style="color: gray;">-- This is almost identical to the instance for FormMessage above.</span>
<span style="color: green;font-weight: bold;">instance</span> <span style="color: blue;">RenderMessage</span> <span style="color: blue;">MyApp</span> <span style="color: blue;">Msg</span> <span style="color: green;font-weight: bold;">where</span>
renderMessage _ [] = renderSwedish <span style="color: gray;">-- Default to Swedish</span>
renderMessage _ (<span style="color: green;">"sv"</span>:ls) = renderSwedish
renderMessage _ (<span style="color: green;">"en"</span>:ls) = renderEnglish
renderMessage m (_ :ls) = renderMessage m ls
<span style="color: gray;">-- The data model.</span>
<span style="color: green;font-weight: bold;">data</span> <span style="color: blue;">Car</span> = <span style="color: blue;">Car</span>
{ carModel :: <span style="color: blue;">Text</span>
, carYear :: <span style="color: blue;">Int</span>
}
<span style="color: green;font-weight: bold;">deriving</span> <span style="color: blue;">Show</span>
<span style="color: gray;">-- In our form we use our messages Model and Year as field labels.</span>
<span style="color: blue;font-weight: bold;">carAForm</span> :: <span style="color: blue;">AForm</span> <span style="color: blue;">MyApp</span> <span style="color: blue;">MyApp</span> <span style="color: blue;">Car</span>
<span style="color: blue;font-weight: bold;">carAForm</span> = <span style="color: blue;">Car</span>
<$> areq textField (fs <span style="color: blue;">Model</span>) <span style="color: blue;">Nothing</span>
<*> areq intField (fs <span style="color: blue;">Year</span>) <span style="color: blue;">Nothing</span>
<span style="color: green;font-weight: bold;">where</span>
fs msg = <span style="color: blue;">FieldSettings</span> msg <span style="color: blue;">Nothing</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">Nothing</span>
<span style="color: blue;font-weight: bold;">carForm</span> :: <span style="color: blue;">Html</span> -> <span style="color: blue;">Form</span> <span style="color: blue;">MyApp</span> <span style="color: blue;">MyApp</span> (<span style="color: blue;">FormResult</span> <span style="color: blue;">Car</span>, <span style="color: blue;">Widget</span>)
<span style="color: blue;font-weight: bold;">carForm</span> = renderTable carAForm
<span style="color: gray;">-- Our handler just shows the form, with submitted values pre-filled.</span>
<span style="color: gray;">-- Here we also use the Please message.</span>
<span style="color: blue;font-weight: bold;">getRootR</span> :: <span style="color: blue;">Handler</span> <span style="color: blue;">RepHtml</span>
<span style="color: blue;font-weight: bold;">getRootR</span> = <span style="color: green;font-weight: bold;">do</span>
((_, widget), enctype) <- runFormGet carForm
defaultLayout [whamlet|
<p>_{<span style="color: blue;">Please</span>}
<form method=get action=@{<span style="color: blue;">RootR</span>} enctype=#{enctype}>
<table
^{widget}
<p><input <span style="color: green;font-weight: bold;">type</span>=submit>
|]
<span style="color: gray;">-- | Launch the app on port 3000.</span>
<span style="color: blue;font-weight: bold;">main</span> :: <span style="color: blue;">IO</span> ()
<span style="color: blue;font-weight: bold;">main</span> = warpDebug <span style="color: teal;">3000</span> <span style="color: blue;">MyApp</span>
</pre></td></tr>
</table><a href="http://flattr.com/thing/396642/Yesod-Cookbook-Internationalized-Form" target="_blank"><br />
<img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-40060370409572876232011-06-17T03:02:00.004-04:002011-09-15T11:09:10.485-04:00Toy URL shortener with Yesod and acid-state<p><strong>Updated 2011-08-31: Modified <code>urlForm</code> to work with Yesod 0.9.1.</strong></p><p>Herein we will create a rudimentary unsafe URL shortener – a toy. We will see how to use David Himmelstrup’s <a href="http://acid-state.seize.it/">acid-state</a> to persist a data structure and how to use Michael Snoyman’s <a href="http://www.yesodweb.com/">Yesod</a> to build a simple web application.</p><p>This URL shortener is unsafe not in the sense of <code>unsafePerformIO</code> or <code>unsafeCoerce</code>, but in the sense that it is wide open to abuse. If you use it as anything other than a toy The Internet (spammers et al) will have you for breakfast. Jason Jacek has written <a href="http://rield.com/faq/why-url-shorteners-are-bad">a good article</a> on the good and bad of URL shorteners; if you are looking for a non-toy URL shortener use one of the products he recommends.</p><p>This post is literate Haskell; just copy and paste it into a <em><a href="http://www.haskell.org/onlinereport/literate.html">.lhs</a></em> file and build/run with GHC.</p><h1 id="preliminaries">Preliminaries</h1><p>Language extensions, imports, and all that. There’s just no way around them!</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="ot">{-# LANGUAGE DeriveDataTypeable #-}</span>
> <span class="ot">{-# LANGUAGE MultiParamTypeClasses #-}</span>
> <span class="ot">{-# LANGUAGE OverloadedStrings #-}</span>
> <span class="ot">{-# LANGUAGE QuasiQuotes #-}</span>
> <span class="ot">{-# LANGUAGE StandaloneDeriving #-}</span>
> <span class="ot">{-# LANGUAGE TemplateHaskell #-}</span>
> <span class="ot">{-# LANGUAGE TypeFamilies #-}</span></code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">import</span> <span class="dt">Control.Exception</span> (bracket)
> <span class="kw">import</span> <span class="dt">Control.Monad.Reader</span> (asks)
> <span class="kw">import</span> <span class="dt">Control.Monad.State</span> (gets, put)
> <span class="kw">import</span> <span class="dt">Data.Acid</span>
> <span class="kw">import</span> <span class="dt">Data.IntMap</span> (<span class="dt">IntMap</span>, <span class="dt">Key</span>, empty, insert, <span class="fu">lookup</span>)
> <span class="kw">import</span> <span class="dt">Data.SafeCopy</span>
> <span class="kw">import</span> <span class="dt">Data.Text</span> (<span class="dt">Text</span>)
> <span class="kw">import</span> <span class="dt">Data.Typeable</span>
> <span class="kw">import</span> <span class="dt">Prelude</span> <span class="kw">hiding</span> (<span class="fu">lookup</span>)
> <span class="kw">import</span> <span class="dt">System</span> (getArgs)
> <span class="kw">import</span> <span class="dt">Yesod</span> <span class="kw">hiding</span> (<span class="dt">Key</span>, insert, <span class="dt">Update</span>, update, get)</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">type</span> <span class="dt">URL</span> <span class="fu">=</span> <span class="dt">Text</span>
> <span class="co">-- type Key = Int is provided by Data.IntMap.</span></code></pre><h1 id="state">State</h1><p>We first create an appropriate (for some definition of appropriate) data structure for storing URLs. Then we will give that data structure ACID (Atomicity, Consistency, Isolation and Durability) guarantees by way of the acid-state package.</p><h2 id="url-storage-data-structure">URL storage data structure</h2><p>We’re going to keep things real simple and stuff our URLs into an IntMap using sequentially increasing keys. We also keep track of the latest key assigned.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">data</span> <span class="dt">URLStore</span> <span class="fu">=</span> <span class="dt">URLStore</span> <span class="dt">Key</span> (<span class="dt">IntMap</span> <span class="dt">URL</span>)</code></pre><p>Now we create the API we will use for our URL store. We need to be able to create an empty store, add URLs, and retrieve the URL corresponding to a given key.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- | Create an empty store.</span>
> <span class="ot">emptyStore </span><span class="ot">::</span> <span class="dt">URLStore</span>
> emptyStore <span class="fu">=</span> <span class="dt">URLStore</span> <span class="dv">0</span> empty</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- | Add an URL to the store. Return the key to the URL together</span>
> <span class="co">-- with the updated store.</span>
> <span class="ot">addURL </span><span class="ot">::</span> <span class="dt">URL</span> <span class="ot">-></span> <span class="dt">URLStore</span> <span class="ot">-></span> (<span class="dt">Key</span>, <span class="dt">URLStore</span>)
> addURL u (<span class="dt">URLStore</span> n m) <span class="fu">=</span> <span class="kw">let</span> k <span class="fu">=</span> n<span class="fu">+</span><span class="dv">1</span> <span class="kw">in</span> (k, <span class="dt">URLStore</span> k (insert k u m))</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- | Retrieve an URL from the store.</span>
> <span class="ot">retrieveURL </span><span class="ot">::</span> <span class="dt">Key</span> <span class="ot">-></span> <span class="dt">URLStore</span> <span class="ot">-></span> <span class="dt">Maybe</span> <span class="dt">URL</span>
> retrieveURL k (<span class="dt">URLStore</span> _ m) <span class="fu">=</span> <span class="fu">lookup</span> k m</code></pre><p>Nothing fancy going on so far, just the plain everyday Haskell you know and love!</p><h2 id="make-our-url-store-acidic-with-acid-state">Make our URL store ACIDic with acid-state</h2><p>Now we’ll take our vanilla URL store and make it ACIDic using acid-state. First we’ll need <code>Typeable</code> and <code>SafeCopy</code> instances.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">deriving</span> <span class="kw">instance</span> <span class="dt">Typeable</span> <span class="dt">URLStore</span>
> <span class="fu">$</span>(deriveSafeCopy <span class="dv">0</span> <span class="ch">'base ''URLStore)</span></code></pre><p>We also have to “port” the add/retrieve API to be ACIDic.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- | Add an URL to the ACIDic store. Return the key to the URL.</span>
> <span class="ot">add </span><span class="ot">::</span> <span class="dt">URL</span> <span class="ot">-></span> <span class="dt">Update</span> <span class="dt">URLStore</span> <span class="dt">Key</span>
> add u <span class="fu">=</span> <span class="kw">do</span>
> (k, store) <span class="ot"><-</span> gets (addURL u)
> put store
> <span class="fu">return</span> k</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- | Retrieve an URL from the ACIDic store.</span>
> <span class="ot">retrieve </span><span class="ot">::</span> <span class="dt">Key</span> <span class="ot">-></span> <span class="dt">Query</span> <span class="dt">URLStore</span> (<span class="dt">Maybe</span> <span class="dt">URL</span>)
> retrieve <span class="fu">=</span> asks <span class="fu">.</span> retrieveURL</code></pre><p>Finally, let some magic happen and, ta-da, we have our ACIDic URL store! In particular this creates <code>Add</code> and <code>Retrieve</code> data constructors that will be used below as proxies for <code>add</code> and <code>retrieve</code>.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="fu">$</span>(makeAcidic <span class="ch">''</span><span class="dt">URLStore</span> [<span class="ch">'add, '</span>retrieve])</code></pre><h1 id="the-yesod-web-app">The Yesod web app</h1><p>All that is missing now is the web app that will use our ACIDic state. We’ll use Yesod to for that but only scratch the surface of all the good stuff Yesod can do (including persistence).</p><p>Seth Falcon has written <a href="http://userprimary.net/posts/2009/01/18/survey-of-url-shortening-service-apis/">a survey of URL shortening service APIs</a>. Our API will is very basic: POST a href parameter to / to get a short URL (a GET will also do the job, I’ll let convenience trump idempotency here).</p><p>First we define the Yesod foundation type <code>URLShort</code> and make it an instance of <code>Yesod</code>. The foundation will have to carry its state.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">data</span> <span class="dt">URLShort</span> <span class="fu">=</span> <span class="dt">URLShort</span> {<span class="ot"> state </span><span class="ot">::</span> <span class="dt">AcidState</span> <span class="dt">URLStore</span> }
> <span class="kw">instance</span> <span class="dt">Yesod</span> <span class="dt">URLShort</span> <span class="kw">where</span> approot _ <span class="fu">=</span> <span class="st">""</span></code></pre><p>Then we define routes (paths) we will use. #Key will match any leading integer and discard trailing junk.</p><pre class="sourceCode"><code class="sourceCode haskell">> mkYesod <span class="st">"URLShort"</span> [parseRoutes<span class="fu">|</span>
> <span class="fu">/</span> <span class="dt">RootR</span> <span class="dt">GET</span> <span class="dt">POST</span>
> <span class="fu">/#</span><span class="dt">Key</span> <span class="dt">RedirectR</span> <span class="dt">GET</span>
> <span class="fu">|</span>]</code></pre><h2 id="url-shortening">URL Shortening</h2><p>The route handlers for / do the URL shortening. The only difference between a GET and a POST is where the query params come from.</p><pre class="sourceCode"><code class="sourceCode haskell">> getRootR <span class="fu">=</span> lookupGetParams <span class="st">"href"</span> <span class="fu">>>=</span> doRootR
> postRootR <span class="fu">=</span> lookupPostParams <span class="st">"href"</span> <span class="fu">>>=</span> doRootR</code></pre><p>When given a single URL store it and display its key and a HTML form for submitting another URL.</p><pre class="sourceCode"><code class="sourceCode haskell">> doRootR [url] <span class="fu">=</span> <span class="kw">do</span>
> acid <span class="ot"><-</span> <span class="fu">fmap</span> state getYesod
> key <span class="ot"><-</span> update' acid (<span class="dt">Add</span> url)
> defaultLayout <span class="fu">$</span> <span class="kw">do</span>
> addHamlet [hamlet<span class="fu">|<</span>a href<span class="fu">=@</span>{<span class="dt">RootR</span>}<span class="fu">#</span>{key}<span class="fu">>@</span>{<span class="dt">RootR</span>}<span class="fu">#</span>{key}<span class="fu">|</span>]
> addWidget urlForm <span class="co">-- Is this "The Right Way"?</span></code></pre><p>Otherwise display only the form.</p><pre class="sourceCode"><code class="sourceCode haskell">> doRootR _ <span class="fu">=</span> defaultLayout urlForm</code></pre><p>Here is the HTML form (we don’t bother with fancy formlets).</p><pre class="sourceCode"><code class="sourceCode haskell">> urlForm <span class="fu">=</span> [whamlet<span class="fu">|</span>
> <span class="fu"><</span>form action<span class="fu">=@</span>{<span class="dt">RootR</span>} method<span class="fu">=</span>post
> <span class="fu"><</span>input <span class="kw">type</span><span class="fu">=</span>text name<span class="fu">=</span>href
> <span class="fu"><</span>input <span class="kw">type</span><span class="fu">=</span>submit value<span class="fu">=</span><span class="dt">Shorten</span><span class="fu">!</span>
> <span class="fu">|</span>]</code></pre><h2 id="redirecting">Redirecting</h2><p>The route handler for /[0–9]* retrieves the appropriate URL and redirects the client. If no URL is found for the key the client is given a 404.</p><pre class="sourceCode"><code class="sourceCode haskell">> getRedirectR key <span class="fu">=</span> <span class="kw">do</span>
> acid <span class="ot"><-</span> <span class="fu">fmap</span> state getYesod
> url <span class="ot"><-</span> query' acid (<span class="dt">Retrieve</span> key)
> <span class="kw">case</span> url <span class="kw">of</span>
> <span class="kw">Just</span> u <span class="ot">-></span> redirectText <span class="dt">RedirectPermanent</span> u
> <span class="kw">Nothing</span> <span class="ot">-></span> notFound
> <span class="fu">return</span> ()</code></pre><p>The <code>return ()</code> at the end is there to help GHC infer a suitable type of getRedirectR.</p><h1 id="applicationification-main">Applicationification (main)</h1><p>Our <code>main</code> runs the yesod application with its AcidState. The port number to run on must be provided. Bad arguments crash (I already mentioned that this is a toy, right?). A <code>bracket</code> ensures that the AcidState is checkpointed and closed on exit.</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="co">-- Provide port number as argument.</span>
> main <span class="fu">=</span> <span class="kw">do</span>
> port <span class="ot"><-</span> <span class="fu">fmap</span> (<span class="fu">read</span> <span class="fu">.</span> <span class="fu">head</span>) getArgs
> bracket (openAcidState emptyStore)
> createCheckpointAndClose
> (warpDebug port <span class="fu">.</span> <span class="dt">URLShort</span>)</code></pre><p>Thanks to the magic of acid-state our URL store is persistent across executions. Go ahead, try it out!</p><h1 id="exercises">Exercises</h1><p>You can move this URL shortener a teenie bit further from toydom and closer to tooldom by implementing one or more of the following:</p><ul><li>Use denser representation than decimal digits;</li>
<li>Don’t store duplicate URLs (reuse old key);</li>
<li>URL preview;</li>
<li>JSON, XML, and raw text content;</li>
<li>Sanity-check submitted URLs;</li>
<li>Filter spam URLs;</li>
</ul><p>From there move on to authentication, statistics, and so on…</p><p>Thanks for reading!</p><a href="http://flattr.com/thing/313341/Toy-URL-shortener-with-Yesod-and-acid-state" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com4tag:blogger.com,1999:blog-2553815923640620572.post-75965519675096940752011-05-30T11:29:00.002-04:002011-05-30T11:34:32.167-04:00ANNOUNCE: dimensional-0.10<p>I just released <a href="http://hackage.haskell.org/package/dimensional-0.10">version 0.10</a> of the <a href="http://dimensional.googlecode.com">dimensional</a> library, adding an <code>Enum</code> instance for quantities. Thus now it is possible to, e.g.:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.Prelude</span><br />> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Prelude</span></code></pre><pre class="sourceCode"><code class="sourceCode haskell">> xs <span class="fu">=</span> [<span class="dv">1</span> <span class="fu">*~</span> meter<span class="fu">..</span>] <span class="co">-- [1 m, 2 m, 3 m...]</span></code></pre><p>However, I just realised that the behaviour may occasionally be surprising unless one keeps in mind that the default increment will be a product of SI base units and the value 1. For example:</p><pre class="sourceCode"><code class="sourceCode haskell">> ys <span class="fu">=</span> [<span class="dv">1</span> <span class="fu">*~</span> kilo meter<span class="fu">..</span>] <span class="co">-- [1000 m, 1001 m, 1002 m...]</span></code></pre><p>In order to avoid shooting oneself in the foot I recommended sticking with the <code>enumFromThen</code> or <code>enumFromThenTo</code> forms:</p><pre class="sourceCode"><code class="sourceCode haskell">> zs <span class="fu">=</span> [<span class="dv">1</span> <span class="fu">*~</span> kilo meter, <span class="dv">2</span> <span class="fu">*~</span> kilo meter<span class="fu">..</span>] <span class="co">-- [1000 m, 2000 m, 3000 m...]</span></code></pre><p>Another option is to use <code>*~~</code> (see <a href="http://flygdynamikern.blogspot.com/2011/04/announce-dimensional-09.html">my previous post</a>):</p><pre class="sourceCode"><code class="sourceCode haskell">> zs' <span class="fu">=</span> [<span class="dv">1</span><span class="fu">..</span>] <span class="fu">*~~</span> kilo meter <span class="co">-- [1000 m, 2000 m, 3000 m...]</span></code></pre><p>In other news I’ve added a “search this blog” widget to the right to help myself find my <a href="http://flygdynamikern.blogspot.com/2009/03/blogging-with-pandoc-literate-haskell.html">pandoc article</a> that I need to refer to every time I post. Feel free to use it!</p><a href="http://flattr.com/thing/293312/ANNOUNCE-dimensional-0-10" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-27870430799997041892011-04-20T09:51:00.001-04:002011-04-20T09:54:02.916-04:00ANNOUNCE: dimensional-0.9<p>I am pleased to announce <a href="http://hackage.haskell.org/package/dimensional-0.9">version 0.9</a> of my <a href="http://dimensional.googlecode.com">dimensional</a> library for arithmetic with statically checked physical dimensions. The differences from version 0.8.2.1 is the specification of fixity for <code>*~~</code> and <code>/~~</code> and their generalization to operate on functors rather than lists. The lack of fixity specifications was a bug; I had always intended them to have the same fixity as the closely related <code>*~</code> and <code>/~</code> (and <code>*</code> and <code>/</code> for that matter).</p><p>For readers unfamiliar with the above operators they are used to relate numerical values with units in order to construct and deconstruct physical quantities. For example:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.Prelude</span><br />> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Prelude</span></code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="ot">x </span><span class="ot">::</span> <span class="dt">Length</span> <span class="dt">Double</span> <span class="co">-- type Length = Quantity DLength</span><br />> x <span class="fu">=</span> <span class="dv">1</span> <span class="fu">*~</span> meter</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="ot">y </span><span class="ot">::</span> <span class="dt">Double</span><br />> y <span class="fu">=</span> x <span class="fu">/~</span> kilo meter <span class="co">-- 0.001</span></code></pre><p>This convention for constructing and deconstructing quantities by multiplication and division respectively is motivated by the <a href="http://physics.nist.gov/Pubs/SP811/sec07.html#7.1"><em>NIST Guide to the SI</em>, section 7.1</a>.</p><p>The <code>*~~</code> and <code>/~~</code> operators are analogous to <code>*~</code> and <code>/~</code> but operate on functors, e.g.:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="ot">xs </span><span class="ot">::</span> [<span class="dt">Length</span> <span class="dt">Double</span>]<br />> xs <span class="fu">=</span> [<span class="dv">1</span><span class="fu">..</span>] <span class="fu">*~~</span> meter</code></pre><pre class="sourceCode"><code class="sourceCode haskell">> <span class="ot">ys </span><span class="ot">::</span> [<span class="dt">Double</span>]<br />> ys <span class="fu">=</span> xs <span class="fu">/~~</span> kilo meter</code></pre><p>Finally an observation for the Haskell community: the Haskell <a href="http://www.haskell.org/haskellwiki/Package_versioning_policy">package versioning policy</a> does not address fixity changes, which I presume should force a major version change. Unless someone either objects or beats me to it I will update the wiki to reflect this.</p><a href="http://flattr.com/thing/171879/ANNOUNCE-dimensional-0-9" target="_blank"> <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-89715029366797003282011-04-09T03:35:00.003-04:002011-04-21T23:48:06.543-04:00ANNOUNCE: normaldistribution-1.1 – Minimum fuss normally distributed random values.<p>I’m pleased to announce the immediate availability of the normaldistribution library on <a href="http://hackage.haskell.org/package/normaldistribution">hackage</a>.</p><p>This purpose of this library is to have a simple API and no dependencies beyond Haskell 98 in order to let you produce normally distributed random values with a minimum of fuss. This library does <em>not</em> attempt to be blazingly fast nor to pass stringent tests of randomness. It attempts to be very easy to install and use while being “good enough” for many applications (simulations, games, etc.). The API builds upon and is largely analogous to that of the Haskell 98 <a href="http://www.haskell.org/onlinereport/random.html">Random</a> module (more recently <a href="http://hackage.haskell.org/packages/archive/random/1.0.0.3/doc/html/System-Random.html">System.Random</a>).</p><p>Pure:</p><pre class="sourceCode"><code class="sourceCode haskell">> (sample,g) <span class="fu">=</span> normal myRandomGen <span class="co">-- using a Random.RandomGen</span>
> samples <span class="fu">=</span> normals myRandomGen <span class="co">-- infinite list</span>
> samples2 <span class="fu">=</span> mkNormals <span class="dv">10831452</span> <span class="co">-- infinite list using a seed</span></code></pre><p>In the IO monad:</p><pre class="sourceCode"><code class="sourceCode haskell">> sample <span class="ot"><-</span> normalIO
> samples <span class="ot"><-</span> normalsIO <span class="co">-- infinite list</span></code></pre><p>With custom mean and standard deviation:</p><pre class="sourceCode"><code class="sourceCode haskell">> (sample,g) <span class="fu">=</span> normal' (mean,sigma) myRandomGen
> samples <span class="fu">=</span> normals' (mean,sigma) myRandomGen
> samples2 <span class="fu">=</span> mkNormals' (mean,sigma) <span class="dv">10831452</span></code></pre><pre class="sourceCode"><code class="sourceCode haskell">> sample <span class="ot"><-</span> normalIO' (mean,sigma)
> samples <span class="ot"><-</span> normalsIO' (mean,sigma)</code></pre><p>Internally the library uses the Box-Muller method to generate normally distributed values from uniformly distributed random values. If more than one sample is needed taking samples off an infinite list (created by e.g. <code>normals</code>) will be roughly twice as efficient as repetedly generating individual samples with e.g. <code>normal</code>.</p><p><strong>Update 2011–04–09:</strong> Changed to reflect version 1.1.</p><p><strong>Update 2011–04–22:</strong> Version 1.1.0.1 released which builds with haskell98-1.1+ (GHC-7.0.1+). No code changes.</p><a href="http://flattr.com/thing/165512/ANNOUNCE-normaldistribution-1-1-Minimum-fuss-normally-distributed-random-values-" target="_blank"><br />
<img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-74744564952688283702011-03-31T11:44:00.001-04:002011-03-31T11:46:17.721-04:00Flattrable Reactive Programming<p>I have occasionally seen these “flattr this!” buttons, notably on the blog of <a href="http://lukepalmer.wordpress.com/">Luke Palmer</a>, and occasionally felt it was exactly what I wanted to do. However, inertia always got the better of me – no doubt I was busy being distracted by some lolcat screaming for adoration.</p><p>Lately I noticed a flattr button on the blog of <a href="http://apfelmus.nfshost.com/">Heinrich Apfelmus</a> too, and again felt a desire to give. Heinrich’s blog was the tipping point (pun intended) that finally got me to actually visit <a href="http://flattr.com">flattr.com</a>, and this great quote from Alexandros closed the sale:</p><blockquote><p><a href="http://flattr.com/inthecomments">This month, thanks to Flattr, I’we shared my world to the world. I earned 0.03 cents - the best 0.03 cents ever!</a></p></blockquote><p>How can that <em>not</em> make me want to give? (Is Alexandros being sarcastic? He looks happy enough in his profile pic…)</p><p>My first flattrs go to Luke and Heinrich; 0.03 cents are coming your way! ;)</p><p>Alexandros gets flattred too. And now that I’ve signed up I’ll be on the lookout for more flattr buttons (so don’t feel bad if you weren’t mentioned here!).</p><p>As an aside, the common denominator that made me want to flattr Luke and Heinrich is their efforts to explore Functional Reactive Programming. It seems to me that much remains to be discovered in the FRP design space and I hope my flattrs encourage these brave explorers to push the boundaries further… Oh, look! <a href="http://conal.net/blog/">Conal Elliott</a> has a flattr button too!</p>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com3tag:blogger.com,1999:blog-2553815923640620572.post-14291018397204154152011-03-28T10:57:00.000-04:002011-03-28T10:57:30.066-04:00Dimensional example: leaky container pressure<p>Herein I demonstrate a calculation performed today in my work. The details are slightly different to protect the innocent but the problem is the same. The purpose of all this is to demonstrate use of the <a href="http://dimensional.googlecode.com"><em>dimensional</em></a> library. What this blog post unfortunately fails to demonstrate is how the compiler helps catch errors in units and formulae, effectively double-checking any derivations for me – this is the real value of dimensional! In case you have never heard of dimensional before here is the blurb from the project site:</p><blockquote>Dimensional is a library providing data types for performing arithmetic with physical quantities and units. Information about the physical dimensions of the quantities/units is embedded in their types and the validity of operations is verified by the type checker at compile time. The boxing and unboxing of numerical values as quantities is done by multiplication and division with units. The library is designed to, as far as is practical, enforce/encourage best practices of unit usage.<br />
</blockquote><br />
<p>This is a literate Haskell program. You can copy and paste this blog post into a <em><a href="http://www.haskell.org/onlinereport/literate.html">.lhs</a></em> file and it should compile and run (provided you have installed dimensional). First the formalities:</p><pre class="sourceCode"><code class="sourceCode haskell">> <span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.Prelude</span><br />> <span class="kw">import</span> <span class="dt">Numeric.Units.Dimensional.NonSI</span><br />> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Prelude</span></code></pre><p>(In the below I have used parentheses rather than juxtaposition to denote function application for functions of time, e.g. <span class="math"><em>p</em>(<em>t</em>)</span>. Does this help or hurt clarity given the subject matter?)</p><p>Consider a leaky container of volume <span class="math"><em>v</em></span> filled with gas to pressure <span class="math"><em>p</em><sub>0</sub></span> and launched into space at time <span class="math"><em>t</em><sub>0</sub></span> (insert favorite monad tutorial joke here). There is a requirement that at some future time <span class="math"><em>t</em><sub>1</sub></span> said container must retain no less than a given amount of gas. The temperature <span class="math"><em>T</em></span> of the container is held constant by a thermal control system so per the <a href="http://en.wikipedia.org/wiki/Ideal_gas_law">ideal gas law</a> (a good enough approximation) we can characterize the requirement to remnant gas by its pressure <span class="math"><em>p</em><sub>min</sub></span>. The problem at hand was to determine the maximum allowable leak rate of the container at <span class="math"><em>t</em><sub>0</sub></span> to ensure that the pressure at time <span class="math"><em>t</em><sub>1</sub></span> is no less than <span class="math"><em>p</em><sub>min</sub></span>.</p><p>Here are the inputs (don’t blame me for the choice of units, this is what I was given):</p><pre class="sourceCode"><code class="sourceCode haskell">> v <span class="fu">=</span> <span class="dv">2</span> <span class="fu">*~</span> liter<br />> t_0 <span class="fu">=</span> <span class="dv">0</span> <span class="fu">*~</span> hour<br />> p_0 <span class="fu">=</span> <span class="dv">750</span> <span class="fu">*~</span> mmHg <span class="co">-- roughly atmospheric pressure</span><br />> t_1 <span class="fu">=</span> <span class="dv">133650</span> <span class="fu">*~</span> hour <span class="co">-- about 15.25 years</span><br />> p_min <span class="fu">=</span> <span class="dv">5</span> <span class="fu">*~</span> mmHg<br />> temp <span class="fu">=</span> fromDegreeCelsiusAbsolute <span class="dv">22</span></code></pre><p>For slow leakage it can be assumed that the leakage rate is proportional to the pressure of the gas inside the container (more generally, the pressure difference between the gas in the container and the surrounding medium). Thus the rate of change of the pressure is described by the first order linear differential equation</p><pre class="sourceCode"><code class="sourceCode haskell">> dpdt(t) <span class="fu">=</span> <span class="fu">negate</span> k <span class="fu">*</span> p(t)</code></pre><p>with solution</p><pre class="sourceCode"><code class="sourceCode haskell">> p(t) <span class="fu">=</span> c <span class="fu">*</span> <span class="fu">exp</span> (<span class="fu">negate</span> k <span class="fu">*</span> t)</code></pre><p>The integration constant <span class="math"><em>c</em></span> is determined from the initial conditions at <span class="math"><em>t</em><sub>0</sub></span>:</p><pre class="sourceCode"><code class="sourceCode haskell">> c <span class="fu">=</span> p_0 <span class="co">-- follows from t_0 = 0 s.</span></code></pre><p>We chose the worst case conditions at <span class="math"><em>t</em><sub>1</sub></span> to determine <span class="math"><em>k</em></span>:</p><pre class="sourceCode"><code class="sourceCode haskell">> k <span class="fu">=</span> <span class="fu">log</span> (c <span class="fu">/</span> p_min) <span class="fu">/</span> t_1</code></pre><p>Now, per the ideal gas law the amount of substance <span class="math"><em>n</em></span> in the container is described by</p><pre class="sourceCode"><code class="sourceCode haskell">> n(t) <span class="fu">=</span> p(t) <span class="fu">*</span> v <span class="fu">/</span> (r <span class="fu">*</span> temp)</code></pre><p>where</p><pre class="sourceCode"><code class="sourceCode haskell">> r <span class="fu">=</span> <span class="dv">8</span><span class="fu">.</span><span class="dv">314472</span> <span class="fu">*~</span> (joule <span class="fu">/</span> (mole <span class="fu">*</span> kelvin))</code></pre><p>is the <a href="http://en.wikipedia.org/wiki/Ideal_gas_constant">ideal gas constant</a>. Differentiating <span class="math"><em>n</em>(<em>t</em>)</span> give the rate of change of substance in the container:</p><pre class="sourceCode"><code class="sourceCode haskell">> dndt(t) <span class="fu">=</span> dpdt(t) <span class="fu">*</span> v <span class="fu">/</span> (r <span class="fu">*</span> temp)</code></pre><p>and the maximum allowed rate of change (leakage rate) at time <span class="math"><em>t</em><sub>0</sub></span> is produced by</p><pre class="sourceCode"><code class="sourceCode haskell">> main <span class="fu">=</span> <span class="fu">print</span> (dndt t_0) <span class="co">-- -8.486687441280605e-10 s^-1 mol</span></code></pre><p>That’s it!</p>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-24032894418470412082009-06-06T17:51:00.002-04:002009-06-06T17:52:46.935-04:00ANNOUNCE: numtype 1.0 — Type-level (low cardinality) integers<p
>Since its inception my <em
><a href="http://dimensional.googlecode.com"
>dimensional</a
></em
> library has been built around a unary type-level representation of integers (<em
>NumTypes</em
>) defined in the <code
>Numeric.NumType</code
> module. This module has proven itself useful outside the context of dimensional and after dragging my feet for a long time I’ve finally gotten around packaging it up in its own library: <em
><a href="http://code.google.com/p/dimensional/wiki/numtype"
>numtype</a
></em
>.</p
><p
>The <code
>Numeric.NumType</code
> module is completely self-contained (only imports <code
>Prelude</code
>) and is heavily commented in a narrative manner inspired by <a href="http://okmij.org/ftp/"
>Oleg Kiselyov</a
>’s expositions. I believe it provides a good case study for type-level programming with multi-parameter type classes (MPTCs) and functional dependencies.</p
><p
>Addition, subtraction, division, and multiplication of NumTypes is supported. NumTypes have no value-level representation but can be converted to any <code
>Num</code
> instance with the <code
>toNum</code
> function.</p
><p
>The numtype library has two significant short-comings:</p
><ul
><li
><p
>Minimal haddocks — as with my dimensional library the literate Haskell source code is the documentation. The flip-side is that the code is very well-commented.</p
></li
><li
><p
>Due to the unary implementation the practical size of the NumTypes is severely limited, making them unsuitable for large-cardinality applications. If you will be working with integers beyond (–20, 20) this package probably isn’t for you.</p
></li
></ul
><p
>(If the second bullet is a show-stopper Edward Kmett’s <em
><a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/type-int"
>type-int</a
></em
> library may be a better choice. Peter Gavin’s <em
><a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/tfp"
>tfp</a
></em
> library also provides type-level integers but uses type families instead of MPTCs and fundeps. I cannot vouch for either of these libraries as I haven’t used them.)</p
><p
>Numtype version 1.0 can be downloaded from <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/numtype"
>Hackage</a
> or the <a href="http://dimensional.googlecode.com"
>dimensional project page</a
>. I’ve also updated dimensional to version 0.8 with the <code
>Numeric.NumType</code
> module removed and Julian <code
>year</code
> and <code
>century</code
> units added. Enjoy!</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com2tag:blogger.com,1999:blog-2553815923640620572.post-9513160583858318992009-05-26T00:14:00.008-04:002009-05-26T00:29:26.384-04:00Benchmarking Amazon EC2 with GHC<p
>My personal computers are pretty old and/or slow. I have an old <em
>PowerBook G4</em
> and a <a href="http://flygdynamikern.blogspot.com/2009/02/arch-linux-on-eee-pc.html"
>newish</a
> <em
>EEE PC</em
>. The PowerBook was top of its class when I got it with most options maxed out. Alas, that was five years ago. The EEE PC is by definition not a top performer, nor does it try to be. I find that when the two machines perform similarly in day-to-day tasks, at least when the EEE PC is in “Super performance” mode.</p
><p
>Truth is that for most of the mundane stuff I do these two machines perform acceptably. I’m obviously not going to be watching any 1080p movies on them, or enjoying the latest games (from a productivity standpoint I’m not sure these are such bad things), but most everything else works fine.</p
><p
>Where I feel the performance does hurt me is when compiling with GHC (or any compiler for that matter, it’s just that GHC is the one I use most). Often I spend way to much of my precious little private developer time waiting for the compiler to finish. This is in stark contrast to the situation at work where I run GHC on a pretty zippy <em
>Dell PowerEdge Blade Server</em
>.</p
><p
>In the near future I expect to be spending more time developing at home and want to be able to do so more efficiently, preferably on par with the situation at work. I could obviously buy shiny new hardware but being a miser (in case you couldn’t already tell based on my hardware) I’m looking for alternatives that would allow me to avoid or defer a hefty up-front investment. One such alternative I’m considering is to rent compute capacity in the <em
>Amazon Elastic Compute Cloud (EC2)</em
>.</p
><p
>EC2 compute capacity is sold in the form of <em
>instances</em
> at an hourly rate ranging from $0.10 to $0.80 depending on capacity/performance plus some small-change for bandwidth and persistent storage. While there are a couple of hurdles to overcome in order to leverage EC2 as a development workstation the first thing I want to do is to make sure it is a goal worthy of pursuing in the first place, i.e. will I get the desired performance gains at a reasonable price?</p
><p
>To at least begin to answer this question I’ve done some informal benchmarking of the aforementioned systems, excluding the pricier EC2 instances. All the regular benchmarking caveats apply and to reinforce the unscientificity of it all I’m not going to bother providing complete specs for the systems. Here are the fundamentals:</p
><ul
><li
><em
>Apple PowerBook G4</em
>: 1.5 GHz PowerPC G4 processor, 2 GB RAM, 5400 rpm HD.</li
><li
><em
>Asus EEE PC 900HA</em
>: 1.6 GHz Intel Atom processor, 1 GB RAM, 4200 rpm HD.</li
><li
><em
>Dell PowerEdge 1855 Blade Server</em
>: Two single-core 3.2 GHz Xeon processors, 2 GB RAM.</li
><li
><em
>Amazon EC2 Small Instance</em
>: 1 EC2 Compute Unit (1 virtual core), 1.7 GB RAM, $0.10 per hour.</li
><li
><em
>Amazon EC2 High-CPU Medium Instance</em
>: 5 EC2 Compute Units (2 virtual cores), 1.7 GB RAM, $0.20 per hour.</li
></ul
><p
>According to Amazon “one EC2 Compute Unit provides the equivalent CPU capacity of a 1.0–1.2 GHz 2007 Opteron or 2007 Xeon processor.”</p
><p
>I figure the results are probably more interesting that the details of the tests so here they are, the systems are ordered by increasing performance which happened to be consistent across the tests:</p
><table
><caption
>Benchmark results, times in seconds, shorter times are better.</caption
><tr class="header"
><th align="left" style="width: 24%;"
></th
><th align="center" style="width: 25%;"
>astro-tables build</th
><th align="center" style="width: 31%;"
>highlighting-kate build</th
><th align="center" style="width: 19%;"
>fad test suite</th
></tr
><tr class="odd"
><td align="left"
>PowerBook G4</td
><td align="center"
>292</td
><td align="center"
>(848)</td
><td align="center"
>28</td
></tr
><tr class="even"
><td align="left"
>EEE PC</td
><td align="center"
>291</td
><td align="center"
>643</td
><td align="center"
>18</td
></tr
><tr class="odd"
><td align="left"
>EC2 Small</td
><td align="center"
>171</td
><td align="center"
>519</td
><td align="center"
>15</td
></tr
><tr class="even"
><td align="left"
>Dell PowerEdge</td
><td align="center"
>75</td
><td align="center"
>260</td
><td align="center"
>6</td
></tr
><tr class="odd"
><td align="left"
>EC2 Medium</td
><td align="center"
>55</td
><td align="center"
>172</td
><td align="center"
>4</td
></tr
></table
><p
>The EEE PC was in “Super Performance” mode during the tests and the PowerBook was at its highest CPU speed. All times are the “real” time as measured by the Unix <em
>time</em
> command and lower numbers are naturally better.</p
><p
>As can be seen an Amazon EC2 Small instance is only marginally faster than the EEE PC. An EC2 High-CPU Medium instance on the other hand is significantly faster than the zippy Dell PowerEdge Blade server. Is either one a good deal? Good question, I think a case could be made either way depending on your priorities but I’m not going to tackle that today.</p
><p
>If you care about the details of the tests read on, if not please move on to your next blog of choice!</p
><h4 id="astro-tables-build"
>astro-tables build</h4
><p
>This package currently consists of a single automatically generated 4000-line monster of a module<a href="#fn1" class="footnoteRef" id="fnref1"
><sup
>1</sup
></a
>. The code is pretty straight-forward but the module takes ages to compile, almost certainly due to me giving the type checker an unnecessarily hard time. I have a trivial rewrite on my todo-list which I expect will shorten the compilation time dramatically but the current form comes in kind of handy for the purposes of this benchmark. The Git repo is <a href="git://github.com/bjornbm/astro-tables.git"
><em
>git://github.com/bjornbm/astro-tables.git</em
></a
> and the commit used in the benchmarking was <em
>e63b8978833878526870b2101697197ff64af593</em
>. I made sure the dependencies were already installed and ran <strong
><code
>time cabal install</code
></strong
>.</p
><h4 id="highlighting-kate-build"
>highlighting-kate build</h4
><p
>From <a href="http://flygdynamikern.blogspot.com/2009/03/blogging-with-pandoc-literate-haskell.html"
>recent memory</a
> I knew that John MacFarlane’s <a href="http://johnmacfarlane.net/highlighting-kate/"
><em
>highlighting-kate</em
></a
> package has a hefty number of modules (the majority of which are also automatically generated) that take a fair amount of time to compile. I downloaded version 0.2.4 from hackage, made sure all dependencies were already installed, and ran <strong
><code
>time cabal install --flags=executable</code
></strong
>.</p
><p
>I ran into one snag with this test: the build wouldn’t complete with GHC 6.10.3 on the PowerBook G4 due to some problem with pcre-light (which tends to give me headaches on pretty much every platform). This particular headache<a href="#fn2" class="footnoteRef" id="fnref2"
><sup
>2</sup
></a
> I was unable to resolve and had to run the test using GHC 6.10.1 on the PowerBook G4.</p
><h4 id="fad-test-suite"
>fad test suite</h4
><p
>Finally I did a runtime performance (as opposed to compilation) benchmark: running the test suite of the <a href="http://flygdynamikern.blogspot.com/2009/04/announce-fad-10-forward-automatic.html"
><em
>fad</em
></a
> library. The Git repo is <a href="git://github.com/bjornbm/fad.git"
><em
>git://github.com/bjornbm/fad.git</em
></a
> and the commit used was <em
>cd2965a6741291570930e4bf6e9f8f9ab64ccadd</em
>. I ran <strong
><code
>ghc --make Test</code
></strong
> and then <strong
><code
>time ./Test</code
></strong
>.</p
><div class="footnotes"
><hr
/><ol
><li id="fn1"
><p
>An implementation of the 678 lunisolar terms and 687 planetary terms of the <a href="http://www.iers.org/documents/publications/tn/tn32/tn32.pdf"
><em
>IAU 2000A Precession-Nutation Model</em
></a
>. <a href="#fnref1" class="footnoteBackLink" title="Jump back to footnote 1">↩</a></p
></li
><li id="fn2"
><p
><code
>gcc: Internal error: Virtual timer expired (program cc1)</code
> <a href="#fnref2" class="footnoteBackLink" title="Jump back to footnote 2">↩</a></p
></li
></ol
></div
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com6tag:blogger.com,1999:blog-2553815923640620572.post-15990944183052917592009-05-10T16:17:00.006-04:002009-05-10T19:17:35.218-04:00May 2009 HCAR Submissions<p
>Last weekend was the <a href="http://www.haskell.org/pipermail/haskell/2009-April/021180.html"
>submission deadline</a
> for contributions to the May 2009 edition of the <a href="http://www.haskell.org/communities/"
><em
>Haskell Communities and Activities Report</em
></a
> (HCAR). I absolutely love the HCAR; it’s a terrific and comprehensive source of information on all the amazing stuff people are doing with Haskell. I’m very grateful to the editor Janis Voightländer (and Andres Löh before him) for compiling the report, in my opinion he does a great service to the Haskell community. I can’t wait to get my hands on the upcoming edition!</p
><p
>Below are my submissions to the HCAR (free blogging material, yay!) with some additional notes.</p
><blockquote><h4 id="dimensional-statically-checked-physical-dimensions"
>dimensional: Statically checked physical dimensions</h4
><p
>Report by: Björn Buckwalter<br
/>Status: active, mostly stable</p
><p
>Dimensional is a library providing data types for performing arithmetics with physical quantities and units. Information about the physical dimensions of the quantities/units is embedded in their types, and the validity of operations is verified by the type checker at compile time. The boxing and unboxing of numerical values as quantities is done by multiplication and division with units. The library is designed to, as far as is practical, enforce/encourage best practices of unit usage.</p
><p
>The core of dimensional is stable with additional units being added on an as-needed basis. In addition to the SI system of units, dimensional has experimental support for user-defined dimensions and a proof-of-concept implementation of the CGS system of units. I am also experimenting with forward automatic differentiation and rudimentary linear algebra.</p
><p
>The current release is compatible with GHC 6.6.x and above and can be downloaded from Hackage or the project web site. The primary documentation is the literate Haskell source code, but the wiki on the project web site has a few usage examples to help with getting started.</p
><h5 id="further-reading"
>Further Reading</h5
><a href="http://dimensional.googlecode.com"
>http://dimensional.googlecode.com</a
></blockquote>
<p
>Dimensional was largely the project that enticed me to learn Haskell, and is the one that I am most proud of to date. It relies on some pretty tricky type-level hackery, stuff I would never have been able to pull off without the help of many papers ranging from <a href="http://okmij.org/ftp/Haskell"
>Oleg Kiselyov’s amazing type-hacks</a
> to Hudak et al’s <a href="http://www.haskell.org/haskellwiki/History_of_Haskell"
><em
>A History of Haskell</em
></a
>.</p
><p
>Its primary shortcoming at present is the lack of Haddock documentation. Dimensional is written in a <a href="http://www.haskell.org/onlinereport/literate.html"
>literate style</a
> and I think anyone reading the source will find the documentation pretty comprehensive and easy to follow (barring the fact that type hacking is pretty tricky business). Alas, with the last few years’ infrastructure improvements and increased (de facto) standardization in the community not having proper haddocks is a wart.</p
><blockquote><h4 id="fad-forward-automatic-differentiation"
>fad: Forward Automatic Differentiation</h4
><p
>Report by: Björn Buckwalter<br
/>Participants: Barak A. Pearlmutter, Jeffrey Mark Siskind<br
/>Status: active</p
><p
>Fad is an attempt to make as comprehensive and usable a forward automatic differentiation (AD) library as is possible in Haskell. Fad (a) attempts to be correct, by making it difficult to accidentally get a numerically incorrect derivative; (b) item provides not only first-derivatives, but also a lazy tower of higher-order derivatives; (c) allows nested use of derivative operators while using the type system to reject incorrect nesting (perturbation confusion); (d) attempts to be complete, in the sense of allowing calculation of derivatives of functions defined using a large variety of Haskell constructs; and (e) tries to be efficient, in the sense of both the defining properties of forward automatic differentiation and in keeping the constant factor overhead as low as possible.</p
><p
>Version 1.0 of fad was uploaded to Hackage on April 3. Recent changes can be found via <code
>git clone git://github.com/bjornbm/fad.git</code
></p
><h5 id="further-reading-1"
>Further Reading</h5
><a href="http://github.com/bjornbm/fad"
>http://github.com/bjornbm/fad</a
><br
/><a href="http://flygdynamikern.blogspot.com/2009/04/announce-fad-10-forward-automatic.html"
>http://flygdynamikern.blogspot.com/2009/04/announce-fad–10-forward-automatic.html</a
></blockquote>
<p
>The majority of work on fad (including most of the above report) is actually being done by <a href="http://www.bcl.hamilton.ie/~barak/"
>Barak Pearlmutter</a
>, principial of the Hamilton Institute’s Brain and Computation Lab. As you can understand his brain is in a different league than mine when it comes to anything related to computation. My contribution at this stage is mostly reviewing his patches (often struggling to understand them) and providing guidance and support on Haskell infrastructure and conventions.</p
><blockquote><h4 id="leapseconds-announced"
>leapseconds-announced</h4
><p
>Report by: Björn Buckwalter<br
/>Status: stable, maintained</p
><p
>The leapseconds-announced library provides an easy to use static LeapSecondTable with the leap seconds announced at library release time. It is intended as a quick-and-dirty leap second solution for one-off analyses concerned only with the past and present (i.e. up until the next as of yet unannounced leap second), or for applications which can afford to be recompiled against an updated library as often as every six months.</p
><p
>Version 2009 of leapseconds-announced contains all leap seconds up to 2009–01–01. A new version will be uploaded if/when the IERS announces a new leap second.</p
><h5 id="further-reading-2"
>Further Reading</h5
><a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/leapseconds-announced"
>http://hackage.haskell.org/cgi-bin/hackage-scripts/package/leapseconds-announced</a
><br
/><a href="http://github.com/bjornbm/leapseconds-announced"
>http://github.com/bjornbm/leapseconds-announced</a
></blockquote>
<p
>Not much to add about leapseconds-announced other than that it fills a need I have. I elaborated a little on what it is (and what it doesn’t try to be) in the <a href="http://thread.gmane.org/gmane.comp.lang.haskell.general/16770"
>announcement thread</a
>.</p
><p
>That’s it! I hope to have another project or two to report on in the November edition…</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-52797911354377049702009-04-02T22:11:00.000-04:002009-04-03T10:44:18.047-04:00ANNOUNCE: fad 1.0 — Forward Automatic Differentiation for Haskell<p
>I’m pleased to announce the initial release of the Haskell <em
>fad</em
> library, developed by Barak A. Pearlmutter and Jeffrey Mark Siskind. Fad provides <em
>Forward Automatic Differentiation</em
> (AD) for functions polymorphic over instances of <code
>Num</code
>. There have been many Haskell implementations of forward AD, with varying levels of completeness, published in papers and <a href="http://www.haskell.org/haskellwiki/Functional_differentiation"
>blog posts</a
>, but alarmingly few of these have made it into hackage — to date Conal Elliott’s <a href="http://www.haskell.org/haskellwiki/Vector-space"
><em
>vector-spaces</em
></a
> package is the only one I am aware of.</p
><p
>Fad is an attempt to make as comprehensive and usable a forward AD package as is possible in Haskell. However, correctness is given priority over ease of use, and this is in my opinion the defining quality of fad. Specifically, Fad leverages Haskell’s expressive type system to tackle the problem of <em
>perturbation confusion</em
>, brought to light in Pearlmutter and Siskind’s 2005 paper <a href="http://www.bcl.hamilton.ie/~qobi/nesting/papers/ifl2005.pdf"
><em
>Perturbation Confusion and Referential Transparency</em
></a
>. Fad prevents perturbation confusion by employing type-level “branding” as proposed by myself in <a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/22308/"
>a 2007 post to haskell-cafe</a
>. To the best of our knowledge all other forward AD implementations in Haskell are susceptible to perturbation confusion.</p
><p
>As this library has been in the works for quite some time it is worth noting that it hasn’t benefited from Conal’s <a href="http://conal.net/papers/beautiful-differentiation/"
>ground-breaking work</a
> in the area. Once we wrap our heads around his beautiful constructs perhaps we’ll be able to borrow some tricks from him.</p
><p
>As mentioned already, fad was developed primarily by Barak A. Pearlmutter and Jeffrey Mark Siskind. My own contribution has been providing Haskell infrastructure support and wrapping up loose ends in order to get the library into a releasable state. Many thanks to Barak and Jeffrey for permitting me to release fad under the BSD license.</p
><p
>Fad resides on <a href="http://github.com/bjornbm/fad/"
>GitHub</a
> and <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/fad"
>hackage</a
> and is only a <code
>cabal install fad</code
> away! What follows is Fad’s <em
>README</em
>, refer to the haddocks for detailed documentation.</p
><blockquote><pre>
Copyright : 2008-2009, Barak A. Pearlmutter and Jeffrey Mark Siskind
License : BSD3
Maintainer : <a href="mailto:bjorn.buckwalter@gmail.com">bjorn.buckwalter@gmail.com</a>
Stability : experimental
Portability: GHC only?
Forward Automatic Differentiation via overloading to perform
nonstandard interpretation that replaces original numeric type with
corresponding generalized dual number type.
Each invocation of the differentiation function introduces a
distinct perturbation, which requires a distinct dual number type.
In order to prevent these from being confused, tagging, called
branding in the Haskell community, is used. This seems to prevent
perturbation confusion, although it would be nice to have an actual
proof of this. The technique does require adding invocations of
lift at appropriate places when nesting is present.
For more information on perturbation confusion and the solution
employed in this library see:
<<a href="http://www.bcl.hamilton.ie/~barak/papers/ifl2005.pdf">http://www.bcl.hamilton.ie/~barak/papers/ifl2005.pdf</a>>
<<a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/22308/">http://thread.gmane.org/gmane.comp.lang.haskell.cafe/22308/</a>>
Installation
============
To install:
cabal install
Or:
runhaskell Setup.lhs configure
runhaskell Setup.lhs build
runhaskell Setup.lhs install
Examples
========
Define an example function 'f':
> import Numeric.FAD
> f x = 6 - 5 * x + x ^ 2 -- Our example function
Basic usage of the differentiation operator:
> y = f 2 -- f(2) = 0
> y' = diff f 2 -- First derivative f'(2) = -1
> y'' = diff (diff f) 2 -- Second derivative f''(2) = 2
List of derivatives:
> ys = take 3 $ diffs f 2 -- [0, -1, 2]
Example optimization method; find a zero using Newton's method:
> y_newton1 = zeroNewton f 0 -- converges to first zero at 2.0.
> y_newton2 = zeroNewton f 10 -- converges to second zero at 3.0.
Credits
=======
Authors: Copyright 2008,
Barak A. Pearlmutter <<a href="mailto:barak@cs.nuim.ie">barak@cs.nuim.ie</a>> &
Jeffrey Mark Siskind <<a href="mailto:qobi@purdue.edu">qobi@purdue.edu</a>>
Work started as stripped-down version of higher-order tower code
published by Jerzy Karczmarczuk <<a href="mailto:jerzy.karczmarczuk@info.unicaen.fr">jerzy.karczmarczuk@info.unicaen.fr</a>>
which used a non-standard standard prelude.
Initial perturbation-confusing code is a modified version of
<<a href="http://cdsmith.wordpress.com/2007/11/29/some-playing-with-derivatives/">http://cdsmith.wordpress.com/2007/11/29/some-playing-with-derivatives/</a>>
Tag trick, called "branding" in the Haskell community, from
Bjorn Buckwalter <<a href="mailto:bjorn.buckwalter@gmail.com">bjorn.buckwalter@gmail.com</a>>
<<a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/22308/">http://thread.gmane.org/gmane.comp.lang.haskell.cafe/22308/</a>>
</pre></blockquote>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com13tag:blogger.com,1999:blog-2553815923640620572.post-17480341030924083772009-03-16T23:26:00.000-04:002009-03-16T23:45:31.113-04:00Space News: U.S. Air Force To Widen Access To Detailed Space Surveillance Data<p
>Revisiting my posts on the <a href="http://flygdynamikern.blogspot.com/2009/02/on-iridium-33-and-kosmos-2251.html"
>Iridium 33/Cosmos 2251 collision</a
> and <a href="http://flygdynamikern.blogspot.com/2009/02/iridium-33-cosmos-2251-and-data.html"
>data</a
>…</p
><p
>The front page article of last week’s Space News (Volume 20, Issue 10, March 9th, 2009) reported that “U.S. Air Force To Widen Access To Detailed Space Surveillance Data” (article quoted in full <a href="http://rescommunis.wordpress.com/2009/03/06/us-air-force-to-widen-access-to-detailed-space-surveillance-data/"
>here</a
>). The short story is that:</p
><blockquote
><p
>The U.S. Air Force has agreed to provide wider access to its high-accuracy catalog showing the whereabouts of orbital debris and operational satellites as part of an effort to enable commercial and non-U.S. government satellite operators to better avoid in-orbit collisions, according to U.S. Air Force officials.</p
></blockquote
><p
>The “high-accuracy catalog” would be what I <a href="http://flygdynamikern.blogspot.com/2009/02/iridium-33-cosmos-2251-and-data.html"
>referred to</a
> as <em
>Special Perturbations (SP) data</em
>. The article reiterates the limitations of the Two-Line Elements currently available to the public:</p
><blockquote
><p
>…U.S. Air Force Space Surveillance Network data is published, but only in a form that satellite operators have long said is not useful for space traffic management. This data, called Two-Line Elements (TLEs), has too great a margin of error to permit operators to act.</p
></blockquote
><p
>And says that:</p
><blockquote
><p
>The U.S. Air Force statement suggests that it will furnish more information to the public to enable operators to make a more highly informed decision.</p
></blockquote
><p
>Apparently a policy if forthcoming. The details of the policy are unknown but it should be announced before June.</p
><p
>All this is of course good news and cause for cautious optimism. Why do I say <em
>cautious</em
>? Here are two quotations from a March 5 roundtable discussion titled <a href="http://www.thespacereview.com/article/1324/1"
><em
>Challenges for Space Policy in 2009</em
></a
>:</p
><blockquote
><p
>We’re horrible at implementing policy, absolutely horrible.</p
></blockquote
><blockquote
><p
>The problem is not that we have insufficient space policy or a bad space policy, but as we now understand, policy is not self-actualizing. We need to have some other mechanisms that take very sound policy and turn them into action and results.</p
></blockquote
><p
>Let’s hope those mechanisms are in place by June.</p
><p
>While on the topic of the Iridium 33/Cosmos 2251 collision: via Jeff Foust’s <a href="http://www.spacepolitics.com/2009/03/10/space-security-hearing-today/"
>spacepolitics.com</a
> (good blog, love the tagline) I read that “some have tried to portray last month’s Iridium-Cosmos satellite collision as either a <a href="http://en.rian.ru/russia/20090303/120392490.html"
>deliberate act by the US</a
> or a <a href="http://www.washingtontimes.com/news/2009/mar/06/strike-from-space/"
>deliberate act by Russia</a
>.” I call bullshit on both of these. The Washington Times editorial is particularly embarrassing in its tin-foil-hattery.</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-53232248506692155312009-03-14T14:39:00.001-04:002009-05-26T00:12:59.412-04:00Blogging with Pandoc, literate Haskell, and a bug<p
>I use John MacFarlane’s <em
><a href="http://johnmacfarlane.net/pandoc/"
>pandoc</a
></em
> for converting my blog entries into HTML. My workflow is roughly:</p
><ol style="list-style-type: decimal;"
><li
>Write my posts <em
>vim</em
> using (<em
>pandoc</em
>’s enhanced) Markdown format.</li
><li
>Store my posts in a private Git repository on GitHub.</li
><li
>Convert posts to pastable HTML using <em
>pandoc</em
> and paste into Blogger.</li
></ol
><p
><em
>pandoc</em
> is a great tool. It is a better Markdown than Markdown and also supports a bunch of other markup formats. The feature set is really extensive with plenty of useful options and sensible defaults. Kudos to John and the other contributors.</p
><p
>My <a href="http://flygdynamikern.blogspot.com/2009/03/extended-sessions-with-haskell-curl.html"
>previous post on <em
>Network.Curl</em
></a
> was the first post where I included significant amounts of source code and was thus my first opportunity to exercise <em
>pandoc</em
>’s syntax high-lighting features. I was fortunate enough that version 1.2 of <em
>pandoc</em
> was released just days prior to my post with support for literate Haskell. The literate Haskell support meant that I could stop worrying about how to avoid my Haskell code being interpreted as Markdown block quotations (and if I need a block quotation I can always use <code
><blockquote></code
> tags).</p
><p
>By default <em
>pandoc</em
> will install without support for syntax high-lighting. To enable syntax high-lighting you must supply the <code
>highlighting</code
> flag when building, e.g. if you are using <em
>cabal</em
>:</p
><pre
><code
>cabal install pandoc --flags=highlighting
</code
></pre
><p
>This triggers installation of John’s <em
>highlighting-kate</em
> library which is used for the syntax high-lighting. A snag you might run into here is the dependence on <em
>pcre-light</em
> which in turn relies on a PCRE dynamic library being available. In my case (on Mac OS 10.4) I had to install PCRE using MacPorts and add <em
>/opt/local/lib</em
> to <code
>$LD_LIBRARY_PATH</code
>.</p
><p
>When editing my posts I want to review occasionally and run <em
>pandoc</em
> with the <code
>--standalone</code
> option to generate a complete HTML document I can view in my browser. However, when pasting into Blogger I only want a fragment and omit said option. The problem with this is that the CSS style definitions used for the syntax high-lighting isn’t included in the fragment. My solution to this problem was to copy the <code
><style></code
> element from the <code
>--standalone</code
> output and paste into the <code
><head></code
> of my Blogger template (immediately prior to <code
></head></code
>).</p
><p
>That’s pretty much it. The complete command I use to generate the fragments I paste into Blogger is:</p
><pre
><code
>pandoc --smart --to=html+lhs input.lhs
</code
></pre
><p
>(I pipe the output into e.g. <em
>pbcopy</em
> or <em
>xclip</em
> to get it straight into the clipboard.)</p
><p
>The <code
>+lhs</code
> portion of the <code
>--to</code
> option tells <em
>pandoc</em
> to keep the bird-tracks (those ’<code
>></code
>’s at the beginning of a line of code). The beauty of this is that readers can copy and paste the entire (as in “Select All”) blog post into a <em
>.lhs</em
> file and it is valid literate Haskell that e.g. <em
>ghc</em
> will happily compile. (Well, at least when copied from Firefox. Safari has the nasty habit of omitting the empty line following a code block which doesn’t make for valid literate Haskell… I’ll be investigating work-arounds.)</p
><p
>When writing my previous post I did notice one discrepancy in the syntax high-lighting. The bird-track on Any line following a end-of-line comment (<code
>--</code
>) wouldn’t be correctly high-lighted. Example:</p
><pre class="sourceCode literatehaskell"><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- | Additional options to simulate submitting the login form.</span
><br
/><span class="Normal NormalText"
>> loginOptions user pass = </span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> CurlPostFields [ </span
><span class="String"
>"login="</span
><span class="Normal NormalText"
> ++ user, </span
><span class="String"
>"password="</span
><span class="Normal NormalText"
> ++ pass ] : method_POST</span
><br
/></code
></pre>
<p
>Depending on your screens calibration it might not stick out like a sore thumb but the middle bird-track there is black while the other two are blueish. This was due to a bug in the syntax high-lighting definition file for literate Haskell (<em
>literate-haskell.xml</em
>) in the <em
>highlighting-kate</em
> package currently on Hackage (version 0.2.3). This is no fault of John’s as that file came straight from the KDE subversion repository. A couple of hours ago I submitted a <a href="http://darcswatch.nomeata.de/repo_http:__johnmacfarlane.net_repos_highlighting-kate.html"
>patch</a
> to John as well as the KDE developers (who have already <a href="http://websvn.kde.org/?view=rev&revision=939498"
>applied it</a
> to the their repo).</p
><p
>If you can’t wait for John to apply the patch to the <em
>highlighting-kate</em
> <a href="http://johnmacfarlane.net/repos/highlighting-kate"
>repo</a
> you can download it from <a href="http://darcswatch.nomeata.de/repo_http:__johnmacfarlane.net_repos_highlighting-kate.html"
>darcswatch</a
> (it’s the one labeled “20090314201157”), apply it to your local copy of John’s repo, <strong
><code
>cabal install</code
></strong
>, and finally <strong
><code
>cabal install pandoc --flags=highlighting --reinstall</code
></strong
>.</p
><p
>With the patch applied the bird-tracks will render properly:</p
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- | Additional options to simulate submitting the login form.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> loginOptions user pass = </span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> CurlPostFields [ </span
><span class="String"
>"login="</span
><span class="Normal NormalText"
> ++ user, </span
><span class="String"
>"password="</span
><span class="Normal NormalText"
> ++ pass ] : method_POST</span
><br
/></code
></pre
><p
><a href="http://www.flickr.com/photos/wapster/1871480771/"
><img src="http://farm3.static.flickr.com/2417/1871480771_291a41e2af.jpg" title="Bird Track, by Podknox (cc)" alt="Bird Track"
/></a
></p
><p
><strong
>Update 2009–03–16:</strong
> John uploaded <em
>highlighting-kate</em
> 0.2.4 (with patches applied) to Hackage today. Reinstall with <em
>cabal</em
> (don’t forget to <strong
><code
>cabal update</code
></strong
> first).</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com6tag:blogger.com,1999:blog-2553815923640620572.post-19912174156761043392009-03-04T21:23:00.000-05:002009-03-16T23:16:31.299-04:00Extended sessions with the Haskell Curl bindings<p
>I recently needed to automate retrieving protected data from a secure web site. I had to:</p
><ol style="list-style-type: decimal;"
><li
>Log into the website with a POST request.</li
><li
>Download the protected data with a GET request.</li
></ol
><p
>All this had to be done using SSL, and I suspected I’d need to handle cookies too.</p
><p
>I had read that <em
>libcurl</em
> had support for sessions and cookies spanning multiple requests, and knew that it could handle SSL. I was aware there is a <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/curl"
>Haskell binding</a
> to <em
>libcurl</em
> (aptly named “curl” but hereafter referred to as <em
>Network.Curl</em
> to avoid confusion) on Hackage so I had my tools cut out for me. While I had used the command line <em
>curl</em
> utility quite a bit I had never programmed against <em
>libcurl</em
> before and had some learning to do.</p
><p
>It wasn’t entirely clear to me from the <a href="http://hackage.haskell.org/packages/archive/curl/latest/doc/html/Network-Curl.html"
>haddocks</a
> how to use <em
>Network.Curl</em
>. This may not be a problem if you are familiar with <em
>libcurl</em
> already (I couldn’t tell) but for me it was quite a hurdle. Googling on the topic I found some blogged examples that got me started but I was unable to find an example demonstrating a multi-request session. However, with the basics from the blogs I was able to return to <em
>Network.Curl</em
> and figure things out by inspecting its source code. I’ll share an example here for the benefit of others who find themselves in the same situation. I’m using version 1.3.4 of <em
>Network.Curl</em
>.</p
><p
>As a contrived example let’s assume we want to write a small program that, given a user name and password, fetches the user’s API token from GitHub. Here is the code (literate Haskell, just copy and paste into a <em
><a href="http://www.haskell.org/onlinereport/literate.html"
>.lhs</a
></em
> file):</p
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> import Network.Curl</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> import System (getArgs)</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> import Text.Regex.Posix</span
><br
/></code
></pre
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- | Standard options used for all requests. Uncomment the @CurlVerbose@</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- option for lots of info on STDOUT.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> opts = [ CurlCookieJar </span
><span class="String"
>"cookies"</span
><span class="Normal NormalText"
> </span
><span class="Comment"
>{- , CurlVerbose True -}</span
><span class="Normal NormalText"
> ]</span
><br
/></code
></pre
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- | Additional options to simulate submitting the login form.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> loginOptions user pass = </span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> CurlPostFields [ </span
><span class="String"
>"login="</span
><span class="Normal NormalText"
> ++ user, </span
><span class="String"
>"password="</span
><span class="Normal NormalText"
> ++ pass ] : method_POST</span
><br
/></code
></pre
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> main = withCurlDo $ </span
><span class="Keyword"
>do</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- Get username and password from command line arguments (will cause</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- pattern match failure if incorrect number of args provided).</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> [user, pass] <- getArgs</span
><br
/></code
></pre
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- Initialize curl instance.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> curl <- initialize</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> setopts curl opts</span
><br
/></code
></pre
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- POST request to login.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> r <- do_curl_ curl </span
><span class="String"
>"https://github.com/session"</span
><span class="Normal NormalText"
> (loginOptions user pass)</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> :: </span
><span class="DataType TypeConstructor"
>IO</span
><span class="Normal NormalText"
> CurlResponse</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>if</span
><span class="Normal NormalText"
> respCurlCode r /= CurlOK || respStatus r /= </span
><span class="DecVal Decimal"
>302</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>then</span
><span class="Normal NormalText"
> </span
><span class="Function"
>error</span
><span class="Normal NormalText"
> $ </span
><span class="String"
>"Failed to log in: "</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> ++ </span
><span class="Function"
>show</span
><span class="Normal NormalText"
> (respCurlCode r) ++ </span
><span class="String"
>" -- "</span
><span class="Normal NormalText"
> ++ respStatusLine r</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>else</span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>do</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- GET request to fetch account page.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> r <- do_curl_ curl (</span
><span class="String"
>"https://github.com/account"</span
><span class="Normal NormalText"
>) method_GET</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> :: </span
><span class="DataType TypeConstructor"
>IO</span
><span class="Normal NormalText"
> CurlResponse</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>if</span
><span class="Normal NormalText"
> respCurlCode r /= CurlOK || respStatus r /= </span
><span class="DecVal Decimal"
>200</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>then</span
><span class="Normal NormalText"
> </span
><span class="Function"
>error</span
><span class="Normal NormalText"
> $ </span
><span class="String"
>"Failed to retrieve account page: "</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> ++ </span
><span class="Function"
>show</span
><span class="Normal NormalText"
> (respCurlCode r) ++ </span
><span class="String"
>" -- "</span
><span class="Normal NormalText"
> ++ respStatusLine r</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>else</span
><span class="Normal NormalText"
> </span
><span class="Function"
>putStrLn</span
><span class="Normal NormalText"
> $ extractToken $ respBody r</span
><br
/></code
></pre
><p
>The first thing to note is that we use <code
>do_curl_</code
> rather than e.g. <code
>curlPost</code
> and <code
>curlGet</code
>. The latter two don’t actually give you access to the response body but instead prints it on <em
>stdout</em
>! The general process is:</p
><ol style="list-style-type: decimal;"
><li
>Initialize a curl instance.</li
><li
>Set options.</li
><li
>Call <code
>do_curl</code
> with the URL and request-specific options.</li
><li
>Inspect <code
>CurlResponse</code
></li
><li
>Repeat from 3 until done.</li
></ol
><p
>Note that the all used of <em
>libcurl</em
> should be wrapped by <code
>withCurlDo</code
>. In the example I wrapped the entire body of <code
>main</code
>. Also note that the type of <code
>do_curl_</code
> must be specified explicitly unless it can be inferred by later use. The <code
>CurlResponse</code
> type specified above uses vanilla <code
>String</code
>s for everything.</p
><p
>For the POST request I added some <code
>CurlPostFields</code
> to the <code
>method_POST</code
> options predefined in the <em
>Network.Curl</em
>. For the GET request’s options since the predefined <code
>method_GET</code
> is sufficient.</p
><p
>A GitHub-specific peculiarity here is the error checking after the POST request. GitHub returns a 302 (“Moved Temporarily”) on successful login and a 200 (“OK”) when the credentials are bad. Stuff like this needs to be figured out on a site-by-site basis.</p
><p
>For completeness here is the function that extracts the token from the response body using a regular expression:</p
><pre class="sourceCode literatehaskell"
><code
><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Comment"
>-- | Extracts the token from GitHub account HTML page.</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> extractToken body = head' </span
><span class="String"
>"GitHub token not found"</span
><span class="Normal NormalText"
> xs</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> </span
><span class="Keyword"
>where</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> head' msg l = </span
><span class="Keyword"
>if</span
><span class="Normal NormalText"
> </span
><span class="Function"
>null</span
><span class="Normal NormalText"
> l </span
><span class="Keyword"
>then</span
><span class="Normal NormalText"
> </span
><span class="Function"
>error</span
><span class="Normal NormalText"
> msg </span
><span class="Keyword"
>else</span
><span class="Normal NormalText"
> </span
><span class="Function"
>head</span
><span class="Normal NormalText"
> l</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> (_,_,_,xs) = body =~ </span
><span class="String"
>"github\\.token (.+)"</span
><br
/><span class="Char Special"
>></span
><span class="Normal NormalText"
> :: (</span
><span class="DataType TypeConstructor"
>String</span
><span class="Normal NormalText"
>, </span
><span class="DataType TypeConstructor"
>String</span
><span class="Normal NormalText"
>, </span
><span class="DataType TypeConstructor"
>String</span
><span class="Normal NormalText"
>,[</span
><span class="DataType TypeConstructor"
>String</span
><span class="Normal NormalText"
>])</span
><br
/></code
></pre
><p
>If you Load this code in <em
>ghci</em
> and type <strong
><code
>:main</code
><em
><code> username password</code></em
></strong
> the Octocat will deliver your token.</p
><p
><a href="http://github.com"
><img src="http://github.com/rmm5t/github-media/raw/master/octocat_stroked.png" title="Octocat, courtesy of GitHub" alt="Octocat, GitHub&rsquo;s mascot"
/></a
></p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com1tag:blogger.com,1999:blog-2553815923640620572.post-49947321889285959202009-02-25T22:30:00.000-05:002009-03-03T21:14:35.844-05:00Programmer Man<p
>While I haven’t tried pair programming I’m intrigued by the idea and would like to give it a shot some time. Rod Hilton recently blogged about <a href="http://www.nomachetejuggling.com/2009/02/21/i-love-pair-programming/"
>his experiences</a
> with pair programming and despite <em
>vim</em
> (+command line) being my primary development environment I have to concede that it makes an interesting as well as entertaining read. As William Pietri noted in the comments the “insights on Programmer Man are both novel and keen” and well worth pondering even if you have no interest in pair programming per se.</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com1tag:blogger.com,1999:blog-2553815923640620572.post-32283190756895461302009-02-21T23:11:00.000-05:002009-03-16T23:43:25.256-04:00Iridium 33, Космос (Cosmos) 2251, and Data<p
>So, finally: data (previous posts <a href="http://flygdynamikern.blogspot.com/2009/02/on-iridium-33-and-kosmos-2251.html"
>here</a
> and <a href="http://flygdynamikern.blogspot.com/2009/02/iridium-33-kosmos-2251-and-odin.html"
>here</a
>).</p
><p
>I may not have said it outright, but I certainly implied that the primary form of orbital data available to operators for collision prediction purposes is Two-Line Elements (TLEs). Specifically the TLEs published by the US Air Force. There are of course other types of data, although they are either not publicly available or not comprehensive.</p
><p
>Here’s a rundown…</p
><h4 id="operator-data"
>Operator data</h4
><p
>By “operator data” I mean whatever orbital data a satellite owner/operator uses for orbit control and/or prediction for its own spacecraft. This data is typically based on radiometric or GPS measurements and is much more accurate than TLE. The obvious shortcoming of operator data is that no such data exists for inactive spacecraft and debris orbiting Earth. Furthermore, satellite operators normally only have access to this information for their own spacecraft. Accurate knowledge of your own spacecraft’s orbit doesn’t really help much when you don’t have accurate information about all the other objects it might collide with.</p
><p
>In the geostationary realm, where the ratio of active spacecraft to debris is still relatively favorable, operators have recently started <a href="http://celestrak.com/publications/AMOS/2008/"
>an effort</a
> to share data between themselves for purposes of collision avoidance. This is a unique cooperation among the otherwise very competitive telecommunication satellite owners (of which my employer, Intelsat, is one) and an important first step to safer satellite operations in the geostationary belt.</p
><p
>In lower orbits, such as those of Iridium 33 and Cosmos 2251, the ratio of operated spacecraft to debris is so small that sharing operator data would only marginally improve safety.</p
><h4 id="two-line-elements"
>Two-Line Elements</h4
><p
>The US Air Force publishes a catalog of orbital data in the form of TLEs for the majority of Earth-orbiting objects through its <a href="http://www.space-track.org"
>space-track.org</a
> web site.</p
><p
>TLEs are based on measurements made by the US Space Surveillance Network (SSN). The measurements are fitted to a relatively simple analytical model (SGP4) by an undisclosed process. The accuracy of any given TLE is generally unknown, perhaps even to the Air Force. Factors affecting the orbit quality are:</p
><ul
><li
>The amount and age of measurements used to generate the TLE,</li
><li
>The applicability of the SGP4 model to the particular orbit and object properties,</li
><li
>The presence of artificial disturbances (i.e. maneuvers) during or after the time when measurements were collected.</li
></ul
><p
>In general the accuracy of TLEs is thought to be on the order of kilometers. However, the TLE catalog also has other problems, notably that classified US spacecraft (and related debris) are purposefully omitted from the catalog and that certain classes of non-classified objects are omitted for technical reasons (e.g. inability to track them).</p
><p
><a href="http://en.wikipedia.org/wiki/United_States_Space_Surveillance_Network"
><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/GEODSS_Diego_Garcia_2006-05-01.jpg/600px-GEODSS_Diego_Garcia_2006-05-01.jpg" alt="GEODSS facility at Diego Garcia"
/></a
></p
><h4 id="special-perturbations-sp-data"
>Special Perturbations (SP) data</h4
><p
>SP data is the moniker for orbital data from a classified catalog maintained by the US Air Force. It is essentially equivalent to the TLE catalog but with higher accuracy data based on a more accurate orbital model. It also includes the classified US spacecraft. The accuracy of SP data isn’t publicly known but it is thought to be significantly better than that of the TLEs.</p
><p
>The SP data catalog is used routinely for collision prediction for the Air Force’s (and other DoD organizations’) satellites as well as NASA missions (notably human spaceflight). However, by virtue of being classified the SP data isn’t generally available to other satellite operators. There is a <a href="http://www.space-track.org/orbitaldatarequestprocess.html"
>process</a
> through which satellite operators can request support from the Air Force to confirm isolated close approaches. This process currently requires the operator to first identify the risk of a close approach by another means (e.g. using TLEs) and then go through a few layers of bureaucracy before the Air Force will investigate the close approach. It works somewhat in the not-too-densely-populated geostationary realm but I cannot see that it would scale to the level of support e.g. Iridium would need.</p
><p
>One can only hope that the collision between Iridium 33 and Cosmos 2251 prompts the Air Force to increase the level of support it provides to satellite operators and streamline the processes involved.</p
><h4 id="discos"
>DISCOS</h4
><p
>The European Space Agency maintains the <a href="http://www.esa.int/SPECIALS/Space_Debris/SEMXP0WPXPF_0.html"
>DISCOS</a
> database (Database and Information System Characterising Objects in Space) which is based primarily on data from the US Space Surveillance Network. I don’t know any details about that data, perhaps it is simply the TLEs that the US Air Force publishes?</p
><p
>Late last year ESA initiated a program to develop its own space tracking capabilities.</p
><h4 id="mit-lincoln-laboratory"
>MIT Lincoln Laboratory</h4
><p
>MIT’s Lincoln Laboratory offers a close approach prediction service to geostationary satellite operators. To my knowledge the data used in the predictions is collected by the laboratory’s own sensors and is comparable to SP data. It’s a good service but the cost for operators is pretty steep (though certainly nowhere near the cost of losing a satellite in a collision) which prevents its use from being ubiquitous.</p
><h4 id="international-scientific-optical-network"
>International Scientific Optical Network</h4
><p
>A relatively new player in this field is the International Scientific Optical Network (<a href="http://www.oosa.unvienna.org/pdf/pres/stsc2009/tech-36.pdf"
>ISON</a
>) coordinated by the Keldysh Institute of Applied Mathematics in Moscow. ISON is a collaboration between 18 scientific institutions in 9 states with the objective of establishing and maintaining a comprehensive database of objects in high altitude orbits (including the geostationary belt). ISON has so far identified several hundred objects not included in the US Air Force’s TLE catalog (roughly half of which are classified US objects).</p
><p
>The quality of ISON’s orbital data seems to be significantly better than TLEs, but at present the networks focus is on tracking object not in the TLE catalog rather than providing comprehensive orbital data for collision prediction purposes. However, this is a player worth keeping an eye on if you are operating geostationary spacecraft.</p
><h4 id="theres-more-to-it"
>There’s more to it…</h4
><p
>As is obvious to anyone working with the problem of satellite close approach prediction and avoidance I done a lot of hand waving and sweeping generalizations in these posts. My intent was never to go into pain-staking detail or to expose every facet of the problems satellite operators face. I am certainly not aware of them all myself despite the problem being part of my everyday work (just today we decided to reschedule a maneuver on one of our satellites in order to maintain safe separation distance during an upcoming close approach with a spent rocket body).</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-5754370777646864272009-02-16T00:15:00.000-05:002009-03-16T23:43:41.636-04:00Iridium 33, Космос (Cosmos) 2251, and Odin<p
>In my <a href="http://flygdynamikern.blogspot.com/2009/02/on-iridium-33-and-kosmos-2251.html"
>previous post</a
> I discussed the difficulties satellite operators like Iridium face in attempting to predict collisions. I’ll talk more about orbital data in the future but in this post I want to revisit the question of whether it makes sense to point fingers at the Russians for having an “out of control” spacecraft (Cosmos 2251) on orbit? Well, one could turn the tables and argue that the finger should be pointed at Iridium, since their spacecraft (Iridium 33) had the capability to maneuver and also was an asset worth protecting. But, as I illustrated previously, it is extremely difficult for a satellite operator in this particular orbital regime (Low Earth Orbits) to predict collisions with high enough confidence to warrant action.</p
><p
>In fact, many satellites in Low Earth Orbits don’t even have a propulsion system, which means that even given perfect information regarding a future collision they would be unable to move out of the way. An example of such a satellite is the Swedish space observatory <a href="http://www.ssc.se/?id=7180"
>Odin</a
> which orbits Earth in a circular polar orbit roughly 600 km above sea level, or 180 km below the altitude at which Iridium 33 and Cosmos 2251 collided. Odin is built and operated by the Swedish Space Corporation, my former employer, and is particularly dear to me as I participated in its launch campaign at Svobodny Cosmodrome, Russia, in 2001.</p
><p
><a href="http://www.yorku.ca/mcdade/"
><img src="http://www.yorku.ca/mcdade/odinlaunch2.jpg" alt="Odin launch"
/></a
></p
><p
>About a year ago Dr T.S. Kelso told me that one day when he had been checking on the close approach predictions from his SOCRATES service he saw a miss distance significantly smaller than he had ever seen before. I don’t remember the exact number but I believe he said it was less than a meter, which is to say it is not a miss at all if the combined dimensions of the involved spacecraft are greater than a meter. One of the objects involved in the prediction was a piece of debris while the other was the still operational Odin. Even with the caveats regarding the inaccuracies of Two-Line Elements T.S. felt compelled to contact Odin’s, to him unknown, operator and warn them of the potential danger. After a fair bit of detective work he eventually got hold of a phone number to the Odin control center at Esrange in northern Sweden. He placed the call and explained the predicament only to find out that Odin did not have maneuvering capability and could do nothing to ameliorate the situation.</p
><p
><a href="http://ttt.astro.su.se/news/20070510en.html"
><img src="http://ttt.astro.su.se/news/20070510_odin.jpg" title="Odin. Credit: Swedish Space Corporation" alt="Odin"
/></a
></p
><p
>So how did it go? Well, since you haven’t heard of this before I don’t have to tell you there was no collision and Odin is still out there doing good science. But the example still serves to illustrate the inability to mitigate a predicted close approach, which would hold true even if the data behind the prediction was better. In light of the fact that many satellites don’t have a propulsion system by design (and consequently have no interest in, or can not benefit from, collision predictions) it appears unreasonable to place blame on Iridium for omission of action, or on the Russians for inability to act. These are just par for the course.</p
><p
>(Now, if there was such a thing as perfect information regarding collision prediction perhaps it would be worthwhile including a minimal propulsion system solely for the purpose of collision avoidance, even on spacecraft like Odin where a propulsion system is otherwise considered unnecessary. Alas, it is not so.)</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-75151830113978925212009-02-13T02:42:00.000-05:002009-03-16T23:43:56.281-04:00Iridium 33 and Космос (Cosmos) 2251<p
>The big news in my industry right now is the collision between the satellites Iridium 33 and Cosmos 2251. While the Cosmos spacecraft was reportedly non-operational since 1995 Iridium 33 was operational and in service.</p
><p
>In some of the press the choice of wording (e.g. “out of control” and “slammed into the Iridium craft”) has been such as to unfairly suggest that Cosmos 2251 was at fault. For example, from <a href="http://news.bbc.co.uk/2/hi/science/nature/7885051.stm"
>BBC News</a
>:</p
><blockquote
><p
>“A collision occurred between an Iridium 33 satellite and a Russian Cosmos 2251 military satellite,” Major General Alexander Yakushin said.</p
><p
>The satellite was launched in 1993 and ceased to function two years later, he said according to the AFP news agency.</p
><p
>Russia has not commented on claims the satellite was out of control.</p
></blockquote
><p
>The Russian Major General said that Cosmos 2251 ceased to function in (or around) 2005, so by definition it is “out of control,” which is to say it was orbiting the Earth as dictated by fairly well understood laws of physics. However, the term “out of control” is used by BBC (and others) in a way that implies that Cosmos 2251 is flying around all over the place in an unpredictable manner endangering other spacecraft left and right.</p
><p
>The truth is, it doesn’t really matter, this could just as well have happened between any two operational spacecraft. The key here is that in general, no one is looking. And even if you are looking, it is difficult to know what to do.</p
><p
>I first heard of the event about twelve hours after the fact from Dr T.S. Kelso at the Center for Space Standards & Innovation. Dr Kelso operates the venerable <a href="http://www.celestrak.com/"
>CelesTrak</a
> website and one of the services his site provides is <a href="http://www.celestrak.com/SOCRATES/"
>SOCRATES</a
> (Satellite Orbital Conjunction Reports Assessing Threatening Encounters in Space). SOCRATES compares Two-Line Elements (parameters describing satellite orbits, hereafter referred to as <em
>TLEs</em
>) from the US Air Force in order to predict close approaches between objects in orbit around Earth. SOCRATES had predicted a close approach between Iridium 33 and Cosmos 2251 of 584 m at the time of collision. This highlights a significant problem: the data generally available to predict close approaches isn’t very accurate. The actual accuracies of any given TLEs are not well known, perhaps not even to the Air Force. In this case the data was obviously off by about 584 m (the satellites themselves may be up to tens of meters large).</p
><p
>So, should Iridium and other satellite operators look out for, and maneuver their satellites to avoid, anything that comes within a given distance of their own spacecraft? Apparently a 584 m predicted miss distance is not safe so for the sake of argument let’s assume that we use that as a safety threshold. Searching for “IRIDIUM” in SOCRATES right now returns 16 close approaches with distances less than 584 m over seven days:</p
><table
><tr class="header"
><th align="left" style="width: 40%;"
>Time of Closest Approach (UTC)</th
><th align="left" style="width: 17%;"
>Object 1</th
><th align="left" style="width: 35%;"
>Object 2</th
><th align="left" style="width: 6%;"
>Min Range (km)</th
></tr
><tr class="odd"
><td align="left"
>2009 Feb 13 14:38:21</td
><td align="left"
>IRIDIUM 16</td
><td align="left"
>COSMOS 1275 DEB</td
><td align="left"
>0.137</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 16 05:47:41</td
><td align="left"
>IRIDIUM 97</td
><td align="left"
>CBERS 1 (ZY 1A)</td
><td align="left"
>0.184</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 13 03:22:09</td
><td align="left"
>IRIDIUM 16</td
><td align="left"
>FENGYUN 1C DEB</td
><td align="left"
>0.213</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 15 23:59:47</td
><td align="left"
>IRIDIUM 45</td
><td align="left"
>SL–8 DEB</td
><td align="left"
>0.251</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 12 19:38:39</td
><td align="left"
>IRIDIUM 24</td
><td align="left"
>COSMOS 1275 DEB</td
><td align="left"
>0.274</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 12 07:19:35</td
><td align="left"
>IRIDIUM 26</td
><td align="left"
>NOAA 6</td
><td align="left"
>0.315</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 12 14:18:32</td
><td align="left"
>IRIDIUM 36</td
><td align="left"
>CZ–4 DEB</td
><td align="left"
>0.348</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 18 18:08:06</td
><td align="left"
>IRIDIUM 59</td
><td align="left"
>COSMOS 990</td
><td align="left"
>0.363</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 16 00:12:50</td
><td align="left"
>IRIDIUM 54</td
><td align="left"
>THORAD AGENA D DEB</td
><td align="left"
>0.373</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 17 07:48:07</td
><td align="left"
>IRIDIUM 38</td
><td align="left"
>DELTA 1 DEB</td
><td align="left"
>0.417</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 17 06:36:02</td
><td align="left"
>IRIDIUM 50</td
><td align="left"
>ARIANE 40 R/B</td
><td align="left"
>0.483</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 12 17:16:04</td
><td align="left"
>IRIDIUM 21</td
><td align="left"
>SL–8 DEB</td
><td align="left"
>0.490</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 18 01:35:15</td
><td align="left"
>IRIDIUM 54</td
><td align="left"
>OPS 5058 (DMSP 5B F2)</td
><td align="left"
>0.491</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 15 03:23:34</td
><td align="left"
>IRIDIUM 11</td
><td align="left"
>SL–18 DEB</td
><td align="left"
>0.495</td
></tr
><tr class="odd"
><td align="left"
>2009 Feb 12 12:41:48</td
><td align="left"
>IRIDIUM 81</td
><td align="left"
>COSMOS 1190</td
><td align="left"
>0.555</td
></tr
><tr class="even"
><td align="left"
>2009 Feb 16 11:51:54</td
><td align="left"
>IRIDIUM 4</td
><td align="left"
>TITAN 3C TRANSTAGE DEB</td
><td align="left"
>0.578</td
></tr
></table
><p
>Note that none of the above include debris originating from the Iridium 33/Cosmos 2251 collision - most likely because the Air Force hasn’t begun to publish that data yet. And we’re only looking at close approaches involving the 92 Iridium spacecraft, while there are <em
>over 10000 known objects</em
> out there. Check out the SOCRATES <a href="http://www.celestrak.com/SOCRATES/top10minrange.asp"
>Top 10</a
> listings at any given time for even closer approaches. The point is that services like SOCRATES predict lots of close approaches where the miss distance is significantly below the known to be unsafe 584 m, but actual collisions are still extremely unlikely and (to date) extremely rare.</p
><p
>Now, from the point of the satellite operator it should be understood that maneuvering a satellite to avoid a conjunction generally carries a quantifiable monetary cost with it. If the available information is so inaccurate you don’t even know for sure if you’ll be improving the situation by maneuvering (which is often the case when the information is TLEs) chances are you’ll do nothing and hope for the best. Indeed, there is a good chance you won’t even bother looking.</p
><p
>What is needed to make it operationally feasible to react to predicted close approaches is better data. Operators like Iridium have to know that if the data says the miss distance is, say, 100 m they are safe, and that for the infrequent cases where the miss distance is less the risk is so high that it is worth doing the analysis and spending the fuel necessary for an avoidance maneuver.</p
><p
>I have more to say on this topic but it’s getting late. In the mean time, check out some <a href="http://www.agi.com/corporate/mediaCenter/news/iridium-cosmos/"
>visualizations</a
> courtesy of Analytical Graphics, Inc.</p
><p
><a href="http://www.agi.com/corporate/mediaCenter/news/iridium-cosmos/"
><img src="http://www.agi.com/images/redlaf/corporate/mediaCenter/news/iridium-cosmos/Cosmos2251_CloseUp.jpg" title="Image courtesy of Analytical Graphics, Inc. (www.agi.com)." alt="Cosmos 2251"
/></a
></p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0tag:blogger.com,1999:blog-2553815923640620572.post-31377247595902073822009-02-12T01:31:00.001-05:002009-06-08T22:44:36.976-04:00Arch Linux in VirtualBox on EEE PC<p
>For background refer to my <a href="http://flygdynamikern.blogspot.com/2009/02/arch-linux-on-eee-pc.html"
>previous post</a
>.</p
><p
>Now I’m going to go into some detail of the Arch Linux (hereafter referred to as <em
>Arch</em
>) installation and configuration process, or at least how it played out for me. I won’t be addressing those parts where the <em
>Beginners Guide</em
> was crystal clear and everything went as expected. I will be addressing the parts where I got confused or alarmed or where things just weren’t working as I would have expected.</p
><h4 id="virtualbox"
>VirtualBox</h4
><p
>I should start off by mentioning the rather significant detail that I decided to install Arch as a guest OS running in VirtualBox under Windows XP. When I started out this seemed like a good idea; I wouldn’t have to worry about repartitioning the drive I currently had Windows XP on, I would be able to familiarize myself with Arch and how well it functions on the EEE PC before committing to it, it would be fun to try out VirtualBox, and if everything was hunky dory I hoped I could just take my VirtualBox disk image and clone it to a physical partition and be done. At that point I’d turn the tables and run Arch as my main OS while booting Windows XP as a VirtualBox guest OS on and as-needed basis.</p
><p
>Turns out I was naive. As I worked my way through the installation and configuration I realized that I’m failing to test how well Arch runs on the EEE PC. The stuff I would expect to be most problematic or difficult to configure doesn’t really come into play when running as guest OS. Video (including “compressed” 1024x768), sound, network cards, wifi, webcam, multi-touch trackpad, power management (including “Super Hybrid Engine”); all these are either not applicable or free-riding on the Windows drivers. I still have no idea how well all these things would work without Windows XP behind the scenes. In addition my Arch installation is configured for the mock hardware interfaces that VirtualBox exposes to it; for all I know it probably won’t run at all outside of VirtualBox!</p
><p
>Even had I realized the above I suspect I would still have chosen to install in VirtualBox first to try things out. Or perhaps I would have opted to try out another distro with a Live CD (or, more specifically, live thumb drive). Anyway, back to the Arch installation process…</p
><h4 id="recovery"
>Recovery</h4
><p
>It turned out the mistake that I was referring to in my previous post wasn’t as fatal as I feared. I was in the <em
>Configure the System</em
> section of the Beginners Guide and believe I had made my way through <em
>initramfs</em
> and was about to select <em
>/etc/rc.conf</em
> in the menu when I inadvertently hit the ESC key. This exited the menu and a bunch of processing commenced, entirely prematurely. I had just skipped the steps where the guide said (with emphasis as it appears in the guide):</p
><blockquote
><p
><em
>Closely following and understanding these steps is of key importance to ensure a properly configured system.</em
></p
></blockquote
><p
>and, a few paragraphs further down:</p
><blockquote
><p
><strong
>Note:</strong
> <em
>It is very important at this point to edit, or at the very least, to verify by opening, every configuration file.</em
> The installer script relies on your input to create these files on your installation. A common error is to skip over these critical steps of configuration.</p
></blockquote
><p
>I was fully expecting to have to wipe everything out and restart the installation procedure from scratch. However, once the configuration was done I was returned to the main menu and, lo and behold, I could back up one step and chose to reconfigure. This I did, following the guide closely, and as far as I can tell all is well. Sometimes you get lucky.</p
><h4 id="general-installation-process"
>General installation process</h4
><p
>I decided to install off the most recent core ISO (<em
>archlinux–2008.06-core-i686.iso</em
>). The relative merits of core vs FTP were unclear at the time but I believe if you use the FTP ISO you’ll end up with an up to date system from the start, while I ended up with eight month old packages.</p
><p
>I’m not particularly fond of the fuzzy compressed mode or scrolling the screen so I chose <code
>vga=771</code
> to get 800x600 resolution instead of <code
>vga=773</code
> and 1024x768. I imagine that without VirtualBox the scrolling and compressed mode wouldn’t have been available at all in which case <code
>vga=773</code
> would be a very poor choice.</p
><p
>The first point of confusion arose when partitioning the hard drive. In the <em
>cfdisk</em
> interface a partition could be flagged as “bootable,” which sounds like it would be a desirable property for the partition with <em
>/boot</em
> filesystem. However, there is no mention of the flag in the Beginners Guide and in the example no flags are set on the partitions. I stayed true to the guide and didn’t set the flag and everything has worked fine. So while there isn’t an error per se in the guide it would be nice if it explicitly mentioned that the flag doesn’t need to be set. It certainly would have saved me some angst.</p
><p
>For the record I didn’t want to deal with deciding what is an appropriate size for all the file systems so I just went with one for <em
>/</em
> and a separate swap partition. It’s probably ridiculously easy to resize partitions after the fact but I wasn’t in a mood to investigate at the time.</p
><p
>At first I disabled crond in <em
>/etc/rc.conf</em
> but later realized I was missing out on good stuff like <em
>updatedb</em
> (necessary for <em
>locate</em
> to work) so I re-enabled it.</p
><p
>Setting up sound with <em
>alsa</em
> had me scratching my head for a while until I realized I had to enable sound for the guest in the VirtualBox settings.</p
><p
>I skipped part IV of the guide since I had already decided to use <em
>xmonad</em
> as my window manager. This was readily accomplished by <strong
><code
>pacman -S xmonad</code
></strong
> and I continued with other packages: <em
>vim</em
>, <em
>texlive</em
>, <em
>firefox</em
>…</p
><p
><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4cB-gbb_7qpjxvUF3FzqCM6nDtebOQf-XTiS8dd1xLECN27wS6DmMl2BTb_qJ3KNtkYdzKPWboiCshK1vx0vby4sOQT-5SZ37zaD8ID6WGtMvTh5TilCeeFqgB3Jv51BtnWwmTYG8cFA/" alt="Tomytronic Pac Man"
/></p
><p
>The first “discrepancy” I noticed occurred when <em
>pacman</em
> was “updating kernel-headers” after installing <em
>cairo</em
>. It reported the rather disconcerting message:</p
><pre
><code
>error: scriptlet failed to execute correctly
</code
></pre
><p
>I don’t mean to imply that the message itself is terribly scary, scriptlet even has a cutesy ring to it, but I’d imagine its not good to have stuff going wrong when messing with your kernel. Anyway, I have no idea what that means or what the scriptlet that failed was supposed to do. The error didn’t show up in <em
>/var/log/pacman.log</em
> so I presumed it must have come from a build script external to <em
>pacman</em
> or something along those lines. The next time I saw a scriptlet fail was when updating <em
>shadow</em
>:</p
><pre
><code
>Fixing gshadow file...
add group 'uucp' in /etc/gshadow ?grpck: the files have been updated
error: scriptlet failed to execute correctly
</code
></pre
><p
>Again not sure what that meant, nor what to do about it. Hoping it was nothing.</p
><h4 id="virtualbox-guest-additions-take-one"
>VirtualBox Guest Additions: Take One</h4
><p
>At some point I realized that to get decent video drivers supporting the native 1024x600 resolution of the EEE PC I had to install the <em
>VirtualBox Guest Additions</em
>. I had the option of installing from the ISO that came with VirtualBox, but there were no instructions specifically for Arch. I saw mention in some forum of a <em
>virtualbox-ose-additions</em
> community package. Doing a <strong
><code
>pacman -Si virtualbox-ose-additions</code
></strong
> revealed that it was version 2.0.4–1 while my installation of VirtualBox is 2.1.2. The build date was 2008–11–12 so I decided to try my luck hoping not much would have changed between the two versions, especially given that the ISO is an auxiliary part of VirtualBox. Well, I was stopped short by <em
>pacman</em
>:</p
><pre
><code
>error: failed to prepare transaction (could not satisfy dependencies)
:: virtualbox-ose-additions-modules: requires kernel26<2.6.28>
</code
></pre
><p
>I checked my <em
>kernel26</em
> and it was version 2.6.25.6–1 which certainly seemed to comply with the stated requirement. However, a <strong
><code
>pacman -Si virtualbox-ose-additions-modules</code
></strong
> revealed the following requirement:</p
><pre
><code
>Depends on : kernel26>=2.6.27 kernel26<2.6.28>
</code
></pre
><p
>OK, my <em
>kernel26</em
> didn’t fulfill the requirements, although the requirement reported wasn’t the one that was violated.</p
><p
>By now I was thinking maybe I should upgrade my <em
>kernel26</em
>. In fact, I was mildly surprised that <em
>pacman</em
> didn’t go ahead and do that for me. I checked with <em
>pacman</em
> and saw that the latest version of <em
>kernel26</em
> is 2.6.28.2–1. It dawned upon me that the reason <em
>pacman</em
> reported the requirement <code
>kernel26<2.6.28</code
> was because that was the one that would have been violated had the <em
>kernel26</em
> been upgraded to the latest version. Makes sense I guess but would have been nice if the error message was more explicit about it.</p
><p
>I decided to hit the AUR site to see if it could shed any additional light on these packages and indeed, there I saw that <em
>virtualbox-ose-additions</em
> had been flagged as out of date! I can’t help but wish that a <em
>pacman</em
> would reveal this rather important piece of information; <code
>pacman -Si</code
> loses a lot of its appeal if I have to double-check each package on the web before installing. (One could argue that <em
>pacman</em
> implicitly “knows” this particular package is out of date by virtue of its dependencies being unsatisfiable, but I believe this is a special case; other packages may have been flagged e.g. for security reasons even though there dependencies are satisfiable.)</p
><p
><strong
>Recommendation:</strong
> Always check package status in AUR before installing, especially before deciding to “try your luck.”</p
><p
>(I later realized that I was using the PUEL VirtualBox and not VirtualBox OSE so the packages in question may never have been applicable in the first place.)</p
><h4 id="upgrading-all-packages"
>Upgrading all packages</h4
><p
>Given that the VirtualBox Guest Additions seem to be particular about the kernel version I decided that it would be a good idea to update the kernel and all my other packages before proceeding. A <strong
><code
>pacman -Su</code
></strong
> identified 76 packages needing upgrades and started downloading (these are presumable the packages that were installed from the eight months old core ISO). Upon completion of the downloads <em
>pacman</em
> complained:</p
><pre
><code
>error: failed to commit transaction (conflicting files)
</code
></pre
><p
>and listed a mass of files in <em
>/usr/lib/klibc/include/asm</em
>. A quick google revealed an <a href="http://www.archlinux.org/news/411/"
>announcement</a
> and fix for this: <strong
><code
>rm /usr/lib/klibc/include/asm</code
></strong
>. Having removed the symlink all 76 packages upgraded just fine.</p
><h4 id="virtualbox-guest-additions-take-two"
>VirtualBox Guest Additions: Take Two</h4
><p
>Back to the VirtualBox Guest Additions; it seemed my only option now was to install them from the ISO. I could either use the ISO provided with my Windows version of VirtualBox or I could install the <em
>virtualbox-additions</em
> package which to my understanding would just download the same ISO for me; I’d still have to mount it and install the actual software myself. I decided to go with the ISO that came with my VirtualBox.</p
><p
>I mounted the ISO in the VirtualBox Media Manager but when attempting to <strong
><code
>mount /media/cdrom</code
></strong
> in Arch I was told that the cdrom was missing from <em
>/etc/fstab</em
>. This was perfectly true; the EEE PC has no optical drive so during Arch configuration I had left the cdrom commented out. At the time I hadn’t fully internalized the distinction between installing straight to the EEE PC vs installing on VirtualBox, and it hadn’t occurred to me that VirtualBox provided emulated optical drives. I uncommented the cdrom in <em
>/etc/fstab</em
> and it mounted without further drama.</p
><p
>The installation instructions for the VirtualBox Guest Additions were conflicting and confusing between the wiki, forums, and VirtualBox manual. The VirtualBox manual recommended installing <em
>dkms</em
> first, but the <em
>dkms</em
> package in AUR was flagged as out of date. I tried my luck with the instructions on the ArchWiki’s VirtualBox page instead; verify <em
>gcc</em
> and <em
>make</em
> are installed and <strong
><code
>sh /media/cdrom/VBoxLinuxAdditions-x86.run</code
></strong
>. The wiki warned of “errors about init scripts and run levels and what not” but to my great surprise everything built and installed with nary a complaint.</p
><h4 id="dont-panic"
><a href="http://www.vanessalebourdais.com/DontPanic.html"
><img src="http://www.vanessalebourdais.com/images/Don'tPanicLG.jpg" alt="Don&rsquo;t Panic!"
/></a
></h4
><p
>I rebooted, and then shutdown. After the shutdown Arch wouldn’t start; it would switch resolution to 800x600 but get stuck there with a black screen. I rebooted in fallback mode, removed <code
>vga=771</code
> from <em
>/boot/grub/menu.lst</em
> and retried. Now that the boot process stayed in 640x480 I could see what was going wrong, although I little idea what it meant:</p
><pre
><code
>Code: Bad EIP value.
EIP: [<00000000>] 0x0 SS:ESP 0068:c042fdf4
Kernel panic - not syncing: Fatal exception in interrupt
</code
></pre
><p
>I guess someone doesn’t like zeroes. Restarted in fallback mode: same error this time! Normal mode: same error. Rebooted the EEE PC completely (this had helped previously with another VirtualBox problem): same error in both modes. I noted that there seemed to be some variation in when in the boot process the kernel panic occurred, although it was always very early. I had recently unplugged the EEE PC at which time it switched to its “Auto Power-Saving” mode with lower (and probably variable) clock speed. I speculated that maybe this mode was causing some random timing error (“not synching,” remember?) in the early bootup process. I changed to the “Super Performance” mode, rebooted Arch, and lo and behold, it worked! Once the boot was complete I switched back to the Auto Power-Saving mode.</p
><p
>I’ve had these kernel panics several times since. Also in Super Performance mode and with AC connected. They’re more frequent when power is disconnected and CPU throttled and I’ve rarely had two in a row with AC connected. I don’t think I had any of these before installing the VirtualBox Guest Additions.</p
><p
><strong
>Recommendation:</strong
> Do not change the resolution of your fallback installation.</p
><p
><strong
>Recommendation:</strong
> If you get kernel panics during bootup disable CPU throttling and if possible connect AC.</p
><h4 id="virtualbox-guest-additions-configuration"
>VirtualBox Guest Additions: Configuration</h4
><p
>I added rc.vboxadd to <em
>/etc/rc.conf</em
>. During bootup the message</p
><pre
><code
>Starting VirtualBox host to guest time synchronization
</code
></pre
><p
>is printed to the console which I presume means that <em
>rc.vboxadd-timesync</em
> is started by <em
>rc.vboxadd</em
> without having to be added individually to the daemons in <em
>/etc/rc.conf</em
>.</p
><p
>When shutting down Arch I noticed the error message:</p
><pre
><code
>/etc/rc.d/functions: line 167: /etc/rc.d/vboxadd-timesync: No such file or directory
</code
></pre
><p
>The correct file name should be <em
>/etc/rc.d/<strong
>rc.</strong
>vboxadd-timesync</em
>. I tried to figure out what was the problem but wasn’t familiar enough with <em
>rc.d</em
> to be able to figure it out. In fact, I couldn’t even locate where the <em
>stop_daemon</em
> function where the error occured was called from.</p
><p
><strong
>Update 2009–02–20:</strong
> Alan Savage figured this one out and submitted a <a href="http://thread.gmane.org/gmane.comp.emulators.virtualbox.devel/1112"
>patch</a
> for it.</p
><p
>Also, running <strong
><code
>/etc/rc.d/rc.vboxadd-timesync start</code
></strong
> (or <strong
><code
>stop</code
></strong
>) from the command line resulted in:</p
><pre
><code
>/etc/rc.d/rc.vboxadd-timesync: line 226: begin: command not found
</code
></pre
><p
>The <code
>begin()</code
> function was indeed missing from the code block that defined functions for Arch so I copied the one from the Gentoo block and inserted it at line 169.</p
><p
><strong
>Update 2009–02–14:</strong
> A better place to copy <code
>begin()</code
> from is the Arch-specific definition in <em
>rc.vboxadd</em
>. I’ve submitted a <a href="http://thread.gmane.org/gmane.comp.emulators.virtualbox.devel/1126"
>patch</a
> for this to the vbox-dev mailing list.</p
><h4 id="configuring-xorg"
>Configuring Xorg</h4
><p
>Here are the contents of the <em
>xorg.conf</em
> file that VirtualBox Guest Additions installed:</p
><pre
><code
># Default xorg.conf for Xorg 1.5+ without PCI_TXT_IDS_PATH enabled.
#
# This file was created by VirtualBox Additions installer as it
# was unable to find any existing configuration file for X.
Section "Device"
Identifier "VirtualBox Video Card"
Driver "vboxvideo"
EndSection
</code
></pre
><p
>My impression was that <em
>Xorg</em
> was supposed to use hal to discover the video modes that the “VirtualBox Video Card” supported, and that the X screen resolution would seamlessly follow the VirtualBox window size. This didn’t work for me and I was stuck with 640x480 with no other modes available according to <em
>xrandr</em
>. I had to add the following to <em
>/etc/xorg.conf</em
> to get additional resolutions:</p
><pre
><code
>Section "Screen"
Identifier "Default Screen"
Device "VirtualBox Video Card"
SubSection "Display"
Modes "1024x600" "800x600" "640x480" "1024x768"
EndSubSection
EndSection
</code
></pre
><p
>(As an aside I also tried generating an <em
>xorg.conf</em
> using <em
>hwd</em
> but when it didn’t use the vboxvideo driver (opting instead for vesa) I didn’t pursue that avenue further.)</p
><p
>The only other problem I’ve had with <em
>Xorg</em
> is that switching modes with <code
>Ctrl+Alt+Keyopad-Plus/Minus</code
> was unreliable at best at rendered the session unusable at worst. I disabled these keys with the <code
>DontZoom</code
> option as described in the <em
>xorg.conf</em
> manpage:</p
><pre
><code
>Section "ServerFlags"
Option "DontZoom" "true" # Disable mode-switching keys.
EndSection
</code
></pre
><p
>Instead I use <em
>xrandr</em
> to switch modes, e.g:</p
><pre
><code
>xrandr --output VBOX1 --mode 1024x768
</code
></pre
><p
>I have set up aliases for this, e.g.:</p
><pre
><code
>alias 1024x768='xrandr --output VBOX1 --mode 1024x768'
</code
></pre
><h4 id="its-a-wrap"
>It’s a wrap!</h4
><p
>That pretty much sums it up. Most everything seems to be in working order now and it’s trivial to install additional software with <em
>pacman</em
> as needed. The one thing I know I’ll want to figure out sooner or later is how to how to “hotswap” keyboard layouts but I’m in no hurry.</p
><p
><a href="http://www.buzzworldbaby.com/swbykicokn.html"
><img src="http://img.inkfrog.com/pix/buzzworld/swdl_123_cotton2.jpg" alt="SwaddleMe"
/></a
></p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com2tag:blogger.com,1999:blog-2553815923640620572.post-24974420692434624162009-02-03T01:41:00.000-05:002009-02-15T20:29:28.800-05:00Arch Linux on EEE PC: Prelude<p
>I’m a long-time (as in since the Motorola 68030 and System 7 days) Mac user and currently own a PowerBook G4 going on it’s fifth year. However, I’ve been following the emergence of netbooks heralded by the EEE PC with a fair amount of interest and in November finally bought myself an EEE PC 900HA (which I may do a mini-review of some day).</p
><p
>I wasn’t thrilled by the prospect of having Windows XP on it but I do live with Windows everyday at work, and given that I spend most of my time in a web browser or terminal window I figured it wouldn’t matter too much. I also told myself I’d install Linux on it fairly immediately. Well, now it’s February. I’ve been putting off the Linux install, struggling along with Cygwin instead. I’d have to say the upside of this was that I’ve had two months to try out Google Chrome. My impression is that Google got a lot of things right and managed to streamline the browsing experience quite a bit; now I’m not at all so content with Firefox and Safari…</p
><p
>Anyway, back on topic, today I decided to take some time to get Linux on the EEE PC. I’ve been deliberating for some time which distro to use; on the one hand there’s Ubuntu which I imagine is friendly as can be and probably a great distro all over, on the other hand I’m eager to try using <em
>xmonad</em
> as my window manager and drawn towards choosing a similarly bare bones distro to run it on. I’ve finally settled on the latter with Arch Linux; the main selling points, in my perception, being:</p
><ul
><li
><a href="http://archhaskell.wordpress.com/"
>Excellent Haskell support</a
>.</li
><li
>The rolling release system.</li
><li
>The package system. I’ve had a good experience with MacPorts, and Arch Linux’s <em
>pacman</em
>/ABS appears to be similar.</li
><li
>The bare-bonesiness. If nothing else I hope to learn quite a bit from installing and configuring Arch Linux. I also imagine that by limiting the installation to what I use and need there’ll be less noise and more signal when I inevitably have to trouble-shoot something.</li
></ul
><p
>I’m working my way through the installation process as I type, and it is indeed a rather arduous process. The <em
>Beginners Guide</em
> to installing and configuring Arch Linux prints to a hefty 53 pages, not counting the 18 page appendix.</p
><p
><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Vanguard_rocket_exlodes.jpg/480px-Vanguard_rocket_exlodes.jpg" alt="Vanguard rocket explodes, December 1957"
/></p
><p
><strong
>Ouch!</strong
> It would appear I just screwed up by hitting the ESC key at an inopportune moment in the installer (my motor memory must have thought I was in <em
>vi</em
>). This appears to have bypassed steps which the guide prefaces by repeated italicized notes regarding their importance. Oh well, I guess that’s as good an excuse as any to cut off this post early and go to bed.</p
><p
>At a later date I’ll comment in more detail on the installation experience; what confused me, what worked, and what didn’t.</p
>Björn Buckwalterhttp://www.blogger.com/profile/14027110650075268096noreply@blogger.com0