<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Conal Elliott &#187; vector space</title>
	<atom:link href="http://conal.net/blog/tag/vector-space/feed" rel="self" type="application/rss+xml" />
	<link>http://conal.net/blog</link>
	<description>Inspirations &#38; experiments, mainly about denotative/functional programming in Haskell</description>
	<lastBuildDate>Thu, 25 Jul 2019 18:15:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.17</generator>
	<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2F&amp;language=en_US&amp;category=text&amp;title=Conal+Elliott&amp;description=Inspirations+%26amp%3B+experiments%2C+mainly+about+denotative%2Ffunctional+programming+in+Haskell&amp;tags=blog" type="text/html" />
	<item>
		<title>Vector space bases via type families</title>
		<link>http://conal.net/blog/posts/vector-space-bases-via-type-families</link>
		<comments>http://conal.net/blog/posts/vector-space-bases-via-type-families#comments</comments>
		<pubDate>Mon, 20 Oct 2008 01:23:27 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[type family]]></category>
		<category><![CDATA[vector space]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=56</guid>
		<description><![CDATA[A basis B of a vector space V is a subset B of V, such that the elements of B are linearly independent and span V. That is to say, every element (vector) of V is a linear combination of elements of B, and no element of B is a linear combination of the other [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p
>A <a href="http://en.wikipedia.org/wiki/Basis_(linear_algebra)" title="Wikipedia article"
  >basis</a
  > <em
  >B</em
  > of a vector space <em
  >V</em
  > is a subset <em
  >B</em
  > of <em
  >V</em
  >, such that the elements of <em
  >B</em
  > are linearly independent and span <em
  >V</em
  >. That is to say, every element (vector) of <em
  >V</em
  > is a linear combination of elements of <em
  >B</em
  >, and no element of <em
  >B</em
  > is a linear combination of the other elements of <em
  >B</em
  >. Moreover, every basis determines a unique decomposition of any member of <em
  >V</em
  > into coordinates relative to <em
  >B</em
  >.</p
>

<p
>This post gives a simple Haskell implementation for a canonical basis of a vector space, and a means of decomposing vectors into coordinates. It uses [indexed type families] (associated types), and is quite general, despite its simplicity.</p
>

<p
>The Haskell module described here is part of the vector-space library (version 0.4 or later), which available on Hackage and a darcs repository. See the <a href="http://haskell.org/haskellwiki/vector-space" title="Wiki page: vector-space"
  >wiki page</a
  >, <a href="http://code.haskell.org/vector-space/doc/html/Data-ABasis.html" title="Interface documentation: Data.ABasis"
  >interface documentation</a
  >, and <a href="http://code.haskell.org/vector-space/doc/html/src/Data-ABasis.html" title="Source module: Data.ABasis"
  >source code</a
  >. The library version described below (0.5 or later) relies on ghc 6.10.</p
>

<p
><strong
  >Edits</strong
  >:</p
>

<ul
><li
  >2008-11-09: Tweaked comment above about version.</li
  ><li
  >2008-02-09: just fiddling around</li
  ></ul
>

<p><!-- without a comment or something here, the last item above becomes a paragraph --><span id="more-56"></span></p>

<div id="additive-groups-and-vector-spaces"
><h3
  >Additive groups and vector spaces</h3
  ><p
  >We&#8217;ll need a bit of preliminary before jumping into basis types.</p
  ><p
  >An <em
    ><a href="http://code.haskell.org/vector-space/doc/html/Data-AdditiveGroup.html" title="Interface documentation: Data.AdditiveGroup"
      >additive group</a
      ></em
    > has addition operation, with an identity (zero) and an additive inverse:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >class</span
      > <span class="dt"
      >AdditiveGroup</span
      > v <span class="kw"
      >where</span
      ><br
       />  (<span class="fu"
      >^+^</span
      >)   <span class="dv"
      >&#8759;</span
      > v &#8594; v &#8594; v<br
       />  zeroV   <span class="dv"
      >&#8759;</span
      > v<br
       />  negateV <span class="dv"
      >&#8759;</span
      > v &#8594; v<br
       /></code
    ></pre
  ><p
  >A <em
    ><a href="http://code.haskell.org/vector-space/doc/html/Data-AVectorSpace.html" title="Interface documentation: Data.AVectorSpace"
      >vector space</a
      ></em
    > is an additive group with scalar multiplication, so it also has an associated type of scalars:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >class</span
      > <span class="dt"
      >AdditiveGroup</span
      > v &#8658; <span class="dt"
      >VectorSpace</span
      > v <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Scalar</span
      > v <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      ><br
       />  (<span class="fu"
      >*^</span
      >) <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Scalar</span
      > v &#8594; v &#8594; v<br
       /></code
    ></pre
  ><p
  >This associated type could instead by written as a functional dependency (fundep). In fact, the type family implementation in ghc 6.9 is not quite up to working with the code in this post, so the library contains a (6.9-friendly) version together with as a fundep (<code
    >Data.VectorSpace</code
    >) and the version given in this post (<code
    >Data.AVectorSpace</code
    >). Sometime after ghc-6.10 is released, I will retire the fundep version and rename <code
    >AVectorSpace</code
    > to <code
    >VectorSpace</code
    >. Similarly, the library temporarily contains <code
    >Data.ABasis</code
    >.</p
  ></div
>

<div id="basis-types"
><h3
  >Basis types</h3
  ><p
  >Since Haskell doesn't have subtyping, we can't represent a basis type directly as a subset. Instead, for an arbitrary vector space <code
    >v</code
    >, represent the (canonical) basis as an associated type, <code
    >Basis v</code
    >, and a function that interprets a basis representation as a vector.</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >class</span
      > <span class="dt"
      >VectorSpace</span
      > v &#8658; <span class="dt"
      >HasBasis</span
      > v <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > v <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      ><br
       />  basisValue   <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Basis</span
      > v &#8594; v<br
       /></code
    ></pre
  ><p
  >Another method extracts coordinates (coefficients) for a vector. Each coordinate is associated with a basis element.</p
  ><pre class="sourceCode haskell"
  ><code
    >  decompose    <span class="dv"
      >&#8759;</span
      > v &#8594; [(<span class="dt"
      >Basis</span
      > v, <span class="dt"
      >Scalar</span
      > v)]<br
       /></code
    ></pre
  ><p
  >We can also reverse the process, recomposing into a vector, by linearly combining the basis elements:</p
  ><pre class="sourceCode haskell"
  ><code
    >linearCombo <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >VectorSpace</span
      > v &#8658; [(v,<span class="dt"
      >Scalar</span
      > v)] &#8594; v<br
       />linearCombo ps <span class="fu"
      >=</span
      > sumV [s <span class="fu"
      >*^</span
      > v <span class="fu"
      >|</span
      > (v,s) &#8592; ps]<br
       /><br
       />recompose <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >HasBasis</span
      > v &#8658; [(<span class="dt"
      >Basis</span
      > v, <span class="dt"
      >Scalar</span
      > v)] &#8594; v<br
       />recompose <span class="fu"
      >=</span
      > linearCombo &#8728; <span class="fu"
      >fmap</span
      > (first basisValue)<br
       /></code
    ></pre
  ><p
  >The defining property is</p
  ><pre class="sourceCode haskell"
  ><code
    >recompose &#8728; decompose &#8801; <span class="fu"
      >id</span
      ><br
       /></code
    ></pre
  ><div class="exercise">
<p
  ><strong
    >Exercise</strong
    >: why might <code
    >decompose &#8728; recompose</code
    > not be the identity? What if the decomposition were represented instead as a <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.html"
    >finite map</a
    >?</p
  ></div>
</div
>

<div id="primitive-bases"
><h3
  >Primitive bases</h3
  ><p
  >Any scalar field is also a vector space over itself. For instance,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="dt"
      >AdditiveGroup</span
      > <span class="dt"
      >Double</span
      > <span class="kw"
      >where</span
      ><br
       />  zeroV   <span class="fu"
      >=</span
      > <span class="dv"
      >0</span
      ><span class="fu"
      >.</span
      ><span class="dv"
      >0</span
      ><br
       />  (<span class="fu"
      >^+^</span
      >)   <span class="fu"
      >=</span
      > (<span class="fu"
      >+</span
      >)<br
       />  negateV <span class="fu"
      >=</span
      > <span class="fu"
      >negate</span
      ><br
       /><br
       /><span class="kw"
      >instance</span
      > <span class="dt"
      >VectorSpace</span
      > <span class="dt"
      >Double</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Scalar</span
      > <span class="dt"
      >Double</span
      > <span class="fu"
      >=</span
      > <span class="dt"
      >Double</span
      ><br
       />  (<span class="fu"
      >*^</span
      >) <span class="fu"
      >=</span
      > (<span class="fu"
      >*</span
      >)<br
       /></code
    ></pre
  ><p
  >The canonical basis of a one-dimensional space has only one element, namely <code
    >1</code
    >, which can be represented with no information.</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="dt"
      >HasBasis</span
      > <span class="dt"
      >Double</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > <span class="dt"
      >Double</span
      > <span class="fu"
      >=</span
      > ()<br
       />  basisValue ()     <span class="fu"
      >=</span
      > <span class="dv"
      >1</span
      ><br
       />  decompose s       <span class="fu"
      >=</span
      > [((),s)]<br
       /></code
    ></pre
  ></div
>

<div id="composing-bases"
><h3
  >Composing bases</h3
  ><p
  >Pairs of additive groups form additive groups:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > (<span class="dt"
      >AdditiveGroup</span
      > u,<span class="dt"
      >AdditiveGroup</span
      > v)<br
       />      &#8658; <span class="dt"
      >AdditiveGroup</span
      > (u,v) <span class="kw"
      >where</span
      ><br
       />  zeroV             <span class="fu"
      >=</span
      > (zeroV,zeroV)<br
       />  (u,v) <span class="fu"
      >^+^</span
      > (u',v') <span class="fu"
      >=</span
      > (u<span class="fu"
      >^+^</span
      >u',v<span class="fu"
      >^+^</span
      >v')<br
       />  negateV (u,v)     <span class="fu"
      >=</span
      > (negateV u,negateV v)<br
       /></code
    ></pre
  ><p
  >Pairs of vector spaces, over the same scalar field, form vector spaces:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > (<span class="dt"
      >VectorSpace</span
      > u,<span class="dt"
      >VectorSpace</span
      > v, <span class="dt"
      >Scalar</span
      > u <span class="fu"
      >~</span
      > <span class="dt"
      >Scalar</span
      > v)<br
       />      &#8658; <span class="dt"
      >VectorSpace</span
      > (u,v) <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Scalar</span
      > (u,v) <span class="fu"
      >=</span
      > <span class="dt"
      >Scalar</span
      > u<br
       />  s <span class="fu"
      >*^</span
      > (u,v) <span class="fu"
      >=</span
      > (s<span class="fu"
      >*^</span
      >u,s<span class="fu"
      >*^</span
      >v)<br
       /></code
    ></pre
  ><p
  >Given vector spaces <code
    >u</code
    > and <code
    >v</code
    >, a basis representation for <code
    >(u,v)</code
    > will be one basis representation or the other, tagged with <code
    >Left</code
    > or <code
    >Right</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > (<span class="dt"
      >HasBasis</span
      > u, <span class="dt"
      >HasBasis</span
      > v, <span class="dt"
      >Scalar</span
      > u <span class="fu"
      >~</span
      > <span class="dt"
      >Scalar</span
      > v)<br
       />      &#8658; <span class="dt"
      >HasBasis</span
      > (u,v) <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (u,v) <span class="fu"
      >=</span
      > <span class="dt"
      >Basis</span
      > u <span class="ot"
      >`Either`</span
      > <span class="dt"
      >Basis</span
      > v<br
       /></code
    ></pre
  ><p
  >The basis vectors themselves will be <code
    >(ub,0)</code
    > or <code
    >(0,vb)</code
    >, where <code
    >ub</code
    > is a basis vector for <code
    >u</code
    >, and <code
    >vb</code
    > is a basis vector for <code
    >v</code
    >. As expected then, the dimensionality of the cross product is the sum of the dimensions.</p
  ><pre class="sourceCode haskell"
  ><code
    >  basisValue (<span class="kw"
      >Left</span
      >  a) <span class="fu"
      >=</span
      > (basisValue a, zeroV)<br
       />  basisValue (<span class="kw"
      >Right</span
      > b) <span class="fu"
      >=</span
      > (zeroV, basisValue b)<br
       /></code
    ></pre
  ><p
  >The decomposition of a vector <code
    >(u,v)</code
    > contains left-tagged decompositions of <code
    >u</code
    > and right-tagged decompositions of <code
    >v</code
    >.</p
  ><pre class="sourceCode haskell"
  ><code
    >  decompose (u,v) <span class="fu"
      >=</span
      > decomp2 <span class="kw"
      >Left</span
      > u <span class="fu"
      >++</span
      > decomp2 <span class="kw"
      >Right</span
      > v<br
       /></code
    ></pre
  ><p
  >where</p
  ><pre class="sourceCode haskell"
  ><code
    >decomp2 <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >HasBasis</span
      > w &#8658; (<span class="dt"
      >Basis</span
      > w &#8594; b) &#8594; w &#8594; [(<span class="dt"
      >Scalar</span
      > w, b)]<br
       />decomp2 inject <span class="fu"
      >=</span
      > <span class="fu"
      >fmap</span
      > (first inject) &#8728; decompose<br
       /></code
    ></pre
  ><p
  >Triples etc, can be handled similarly. Instead, the library implementation reduces them to the pair case:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > ( <span class="dt"
      >HasBasis</span
      > u, s <span class="fu"
      >~</span
      > <span class="dt"
      >Scalar</span
      > u<br
       />         , <span class="dt"
      >HasBasis</span
      > v, s <span class="fu"
      >~</span
      > <span class="dt"
      >Scalar</span
      > v<br
       />         , <span class="dt"
      >HasBasis</span
      > w, s <span class="fu"
      >~</span
      > <span class="dt"
      >Scalar</span
      > w )<br
       />      &#8658; <span class="dt"
      >HasBasis</span
      > (u,v,w) <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (u,v,w) <span class="fu"
      >=</span
      > <span class="dt"
      >Basis</span
      > (u,(v,w))<br
       />  &#8943;<br
       /></code
    ></pre
  ><p
  ><strong
    >Exercise</strong
    >: complete this instance definition (without peeking).</p
  ></div
>

<div id="bases-in-spaces"
><h3
  >Bases in spaces</h3
  ><p
  >What about other vector spaces, particularly infinite dimensional ones? The result type for <code
    >decompose</code
    > is not convenient:</p
  ><pre class="sourceCode haskell"
  ><code
    >decompose <span class="dv"
      >&#8759;</span
      > v &#8594; [(<span class="dt"
      >Basis</span
      > v, <span class="dt"
      >Scalar</span
      > v)]<br
       /></code
    ></pre
  ><p
  >Moreover, its definition for pair types would have to be changed, e.g., to use interleaving instead of append. On the other hand, this type can be thought of as an association list, representing <code
    >Basis v &#8594; Scalar v</code
    >. Instead, we might use the function representation directly:</p
  ><pre class="sourceCode haskell"
  ><code
    >decompose <span class="dv"
      >&#8759;</span
      > v &#8594; (<span class="dt"
      >Basis</span
      > v &#8594; <span class="dt"
      >Scalar</span
      > v)<br
       /></code
    ></pre
  ><p
  >In that case, the definition of <code
    >decompose</code
    > on pairs is</p
  ><pre class="sourceCode haskell"
  ><code
    >decompose (u,v) <span class="fu"
      >=</span
      > decompose u <span class="ot"
      >`either`</span
      > decompose v<br
       /></code
    ></pre
  ><p
  >which beautifully mirrors the basis type definition:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (u,v) <span class="fu"
      >=</span
      > <span class="dt"
      >Basis</span
      > u <span class="ot"
      >`Either`</span
      > <span class="dt"
      >Basis</span
      > v<br
       /></code
    ></pre
  ><p
  >I guess we'd have to somehow extend the definition of <code
    >recompose</code
    > as well, or avoid it.</p
  ><p
  >One example of an infinite dimensional vector space is a function over an infinite domain. The additive group and vector space instances follow a standard form for applicative functors applied to an additive group or vector space. In this case, the applicative functor is <code
    >((&#8594;) a)</code
    >.</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="dt"
      >AdditiveGroup</span
      > v &#8658; <span class="dt"
      >AdditiveGroup</span
      > (a &#8594; v) <span class="kw"
      >where</span
      ><br
       />  zeroV   <span class="fu"
      >=</span
      > pure   zeroV<br
       />  (<span class="fu"
      >^+^</span
      >)   <span class="fu"
      >=</span
      > liftA2 (<span class="fu"
      >^+^</span
      >)<br
       />  negateV <span class="fu"
      >=</span
      > <span class="fu"
      >fmap</span
      >   negateV<br
       /><br
       /><span class="kw"
      >instance</span
      > <span class="dt"
      >VectorSpace</span
      > v &#8658; <span class="dt"
      >VectorSpace</span
      > (a &#8594; v) <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Scalar</span
      > (a &#8594; v) <span class="fu"
      >=</span
      > <span class="dt"
      >Scalar</span
      > v<br
       />  (<span class="fu"
      >*^</span
      >) s <span class="fu"
      >=</span
      > <span class="fu"
      >fmap</span
      > ((<span class="fu"
      >*^</span
      >) s)<br
       /></code
    ></pre
  ><p
  >As a basis for a function space <code
    >a&#8594;u</code
    >, let's use the subset of functions that map one domain value to some basis vector for <code
    >u</code
    > and map all other domain values to zero. By linearly combining these functions, we can construct <em
    >any</em
    > function in <code
    >a&#8594;u</code
    > that is nonzero for finitely many domain values. If we stretch the notion of linear combinations beyond finite combinations, perhaps we can go further and cover at least the countably infinite domain types.</p
  ><p
  >To represent these functions, it suffices to record the choice of domain element and the representation of the corresponding basis vector for <code
    >u</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > (<span class="kw"
      >Eq</span
      > a, <span class="dt"
      >HasBasis</span
      > u) &#8658; <span class="dt"
      >HasBasis</span
      > (a &#8594; u) <span class="kw"
      >where</span
      ><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (a &#8594; u) <span class="fu"
      >=</span
      > (a, <span class="dt"
      >Basis</span
      > u)<br
       /><br
       />  basisValue (a,b) a' <span class="fu"
      >|</span
      > a &#8801; a'   <span class="fu"
      >=</span
      > basisValue b<br
       />                      <span class="fu"
      >|</span
      > <span class="fu"
      >otherwise</span
      > <span class="fu"
      >=</span
      > zeroV<br
       /></code
    ></pre
  ><p
  >The actual implementation is a bit more efficient, avoiding recomputation of <code
    >basisValue b</code
    > for each <code
    >a'</code
    >.</p
  ><p
  >Decomposing a function into its coordinates is even simpler:</p
  ><pre class="sourceCode haskell"
  ><code
    >  decompose g (a,b) <span class="fu"
      >=</span
      > decompose (g a) b<br
       /></code
    ></pre
  ></div
>

<div id="some-isomorphisms"
><h3
  >Some isomorphisms</h3
  ><p
  >This instance rule for functions will be applied repeatedly for curried functions. For instance,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Basis</span
      > (a &#8594; b &#8594; u) &#8801; (a, (b, <span class="dt"
      >Basis</span
      > u))<br
       /></code
    ></pre
  ><p
  >The isomorphic uncurried form has an isomorphic basis:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Basis</span
      > ((a,b) &#8594; u) &#8801; ((a,b), <span class="dt"
      >Basis</span
      > u)<br
       /></code
    ></pre
  ><p
  >Pairing in the range instead of domain gives rise to another pair of isomorphisms:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Basis</span
      > (a &#8594; (b,c)) &#8801; (a, <span class="dt"
      >Basis</span
      > b <span class="ot"
      >`Either`</span
      > <span class="dt"
      >Basis</span
      > c)<br
       /><br
       /><span class="dt"
      >Basis</span
      > ((a &#8594; b, a &#8594; c)) &#8801; (a, <span class="dt"
      >Basis</span
      > b) <span class="ot"
      >`Either`</span
      > (a, <span class="dt"
      >Basis</span
      > c)<br
       /></code
    ></pre
  ><p
  >The rules for basis types look like logarithms, especially if we add a basis for <code
    >()</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > () <span class="fu"
      >=</span
      > <span class="dt"
      >Void</span
      ><br
       /><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (u,v) <span class="fu"
      >=</span
      > <span class="dt"
      >Basis</span
      > u <span class="ot"
      >`Either`</span
      > <span class="dt"
      >Basis</span
      > v<br
       /><br
       />  <span class="kw"
      >type</span
      > <span class="dt"
      >Basis</span
      > (a &#8594; u) <span class="fu"
      >=</span
      > (a, <span class="dt"
      >Basis</span
      > u)<br
       /></code
    ></pre
  ><p
  >Compare with:</p
  ><div class=math-inset>
<p
  ><span class="math"
    >log 1 = 0</span
    ></p
  ><p
  ><span class="math"
    >log (<em
      >u</em
      > × <em
      >v</em
      >) = log <em
      >u</em
      > + log <em
      >v</em
      ></span
    ></p
  ><p
  ><span class="math"
    >log (<em
      >u</em
      ><sup
      ><em
    >a</em
    ></sup
      >) = <em
      >a</em
      >  ×  log <em
      >u</em
      ></span
    ></p
  ></div>
<p
  >The rules are also essentially the same as the ones used for <a href="http://conal.net/blog/posts/elegant-memoization-with-functional-memo-tries/" title="blog post"
    >memo tries</a
    >, but phrased in terms of logarithms instead of (explicit) exponents.</p
  ></div
>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=56&amp;md5=a2d7fd58abdcfaf95a7b51539ab9cfff"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/vector-space-bases-via-type-families/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fvector-space-bases-via-type-families&amp;language=en_GB&amp;category=text&amp;title=Vector+space+bases+via+type+families&amp;description=A+basis+B+of+a+vector+space+V+is+a+subset+B+of+V%2C+such+that+the+elements+of+B+are+linearly+independent+and+span+V.+That+is+to+say%2C...&amp;tags=type+family%2Cvector+space%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
