Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>(Note: I have only type-checked (and not actually run) any of this code.)</p> <p><strong>Approach 1</strong></p> <p>Actually, you <em>can</em> manipulate proofs by storing them in GADTs. You'll need to turn on <code>ScopedTypeVariables</code> for this approach to work.</p> <pre><code>data Proof n where NilProof :: Proof Ze ConsProof :: (n + Su Ze) ~ Su n =&gt; Proof n -&gt; Proof (Su n) class PlusOneIsSucc n where proof :: Proof n instance PlusOneIsSucc Ze where proof = NilProof instance PlusOneIsSucc n =&gt; PlusOneIsSucc (Su n) where proof = case proof :: Proof n of NilProof -&gt; ConsProof proof ConsProof _ -&gt; ConsProof proof rev :: PlusOneIsSucc n =&gt; Vec a n -&gt; Vec a n rev = go proof where go :: Proof n -&gt; Vec a n -&gt; Vec a n go NilProof Nil = Nil go (ConsProof p) (Cons x xs) = go p xs `append` Cons x Nil </code></pre> <p>Actually, perhaps interesting motivation for the <code>Proof</code> type above, I originally had just</p> <pre><code>data Proof n where Proof :: (n + Su Ze) ~ Su n =&gt; Proof n </code></pre> <p>But, this didn't work: GHC rightly complained that just because we know <code>(Su n)+1 = Su (Su n)</code> doesn't imply that we know <code>n+1 = Su n</code>, which is what we need to know to make the recursive call to <code>rev</code> in the <code>Cons</code> case. So I had to expand the meaning of a <code>Proof</code> to include a proof of all equalities for naturals up to and including <code>n</code> -- essentially a similar thing to the strengthening process when moving from induction to strong induction.</p> <p><strong>Approach 2</strong></p> <p>After a bit of reflection, I realized that it turns out the class is a bit superfluous; that makes this approach especially nice in that it doesn't require any extra extensions (even <code>ScopedTypeVariables</code>) and doesn't introduce any extra constraints to the type of <code>Vec</code>.</p> <pre><code>data Proof n where NilProof :: Proof Ze ConsProof :: (n + Su Ze) ~ Su n =&gt; Proof n -&gt; Proof (Su n) proofFor :: Vec a n -&gt; Proof n proofFor Nil = NilProof proofFor (Cons x xs) = let rec = proofFor xs in case rec of NilProof -&gt; ConsProof rec ConsProof _ -&gt; ConsProof rec rev :: Vec a n -&gt; Vec a n rev xs = go (proofFor xs) xs where go :: Proof n -&gt; Vec a n -&gt; Vec a n go NilProof Nil = Nil go (ConsProof p) (Cons x xs) = go p xs `append` Cons x Nil </code></pre> <p><strong>Approach 3</strong></p> <p>Alternately, if you switch the implementation of <code>rev</code> a bit to cons the last element onto the reversed initial segment of the list, then the code can look a bit more straightforward. (This approach also requires no additional extensions.)</p> <pre><code>class Rev n where initLast :: Vec a (Su n) -&gt; (a, Vec a n) rev :: Vec a n -&gt; Vec a n instance Rev Ze where initLast (Cons x xs) = (x, xs) rev x = x instance Rev n =&gt; Rev (Su n) where initLast (Cons x xs) = case initLast xs of (x', xs') -&gt; (x', Cons x xs') rev as = case initLast as of (a, as') -&gt; Cons a (rev as') </code></pre> <p><strong>Approach 4</strong></p> <p>Just like approach 3, but again observing that the type classes are not necessary.</p> <pre><code>initLast :: Vec a (Su n) -&gt; (a, Vec a n) initLast (Cons x xs) = case xs of Nil -&gt; (x, Nil) Cons {} -&gt; case initLast xs of (x', xs') -&gt; (x', Cons x xs') rev :: Vec a n -&gt; Vec a n rev Nil = Nil rev xs@(Cons {}) = case initLast xs of (x, xs') -&gt; Cons x (rev xs') </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload