Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Actually the function you've given in the question compiles fine. You <em>would</em> get the error you've quoted if what you had was instead:</p> <pre><code>myzip :: [a] -&gt; [b] -&gt; [(a, b)] myzip (a:b) (z:g) | b == [] = [] | g == [] = [] | otherwise = (a, z) : myzip b g </code></pre> <p>With an explicit type signature saying that <code>myzip</code> works on list of <em>any</em> types <code>a</code> and <code>b</code>. But you've used <code>b == []</code> and <code>g == []</code>. The equality operator <em>isn't</em> defined on any type, only on types which are a member of the <code>Eq</code> type class, so the code you've written doesn't match the type you gave.</p> <p>This is what the error message says pretty straightforwardly, but if you're just learning and haven't gotten up to type classes yet, then it's a bit unclear.</p> <p>If you change the type signature for <code>myzip</code> to say that <code>a</code> and <code>b</code> need to be members of the <code>Eq</code> type class, then the code you gave will work:</p> <pre><code>myzip :: (Eq a, Eq b) =&gt; [a] -&gt; [b] -&gt; [(a, b)] </code></pre> <p>Or if you leave the type signature off entirely (as you did in the question), GHC actually infers this type from the fact that you used the <code>==</code> operator, and the code simply compiles as-is.</p> <p>However, checking whether a list is empty can be done without using the <code>==</code> operator, so you can write <code>myzip</code> so that it really does operate on any types <code>a</code> and <code>b</code>. One way is to use the <code>null</code> function:</p> <pre><code>myzip :: [a] -&gt; [b] -&gt; [(a, b)] myzip (a:b) (z:g) | null b = [] | null g = [] | otherwise = (a, z) : myzip b g </code></pre> <p>But a much more common way is to simply use multiple equations to define <code>myzip</code>, with base cases matching against the pattern <code>[]</code> and a main case that gets to assume that the lists are non-empty:</p> <pre><code>myzip :: [a] -&gt; [b] -&gt; [(a, b)] myzip (a:[]) _ = [] myzip _ (z:[]) = [] myzip (a:b) (z:g) = (a, z) : myzip b g </code></pre> <p>Note that this style has also made it obvious that there's a bug in your implementation. You're throwing away the last <code>a</code> or <code>z</code>, and there's no case for when the lists are completely empty!</p> <p>When your equation said <code>myzip (a:b) (z:g)</code> and <em>then</em> checked <code>b</code> and <code>g</code> against the empty list, it was actually checking the wrong thing too late. You don't need to check if <code>b</code> is <code>[]</code>, you need to check whether the <em>whole</em> list was empty. But you'd already assumed it wasn't empty and decomposed it into <code>a:b</code>. This results in your code (a) returning the wrong result, because it discards the last pair of elements it should be zipping and (b) producing an error when one of the arguments is the empty list.</p> <p>Recursion on lists normally looks more like this:</p> <pre><code>myzip :: [a] -&gt; [b] -&gt; [(a, b)] myzip [] _ = [] myzip _ [] = [] myzip (a:b) (z:g) = (a, z) : myzip b g </code></pre> <p>This behaves correctly.</p>
    singulars
    1. This table or related slice is empty.
    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