Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is a well-known gotcha about contexts for data declaration. If you define <code>data Ord a =&gt; Tree a = ...</code> all it does is force any function that mentions <code>Tree a</code> to have an <code>Ord a</code> context. This doesn't save you any typing, but on the plus side an explicit context is clear about what's needed.</p> <h1>GADTs to the rescue!</h1> <p>The workaround is to use <a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#generalised-algebraic-data-types-gadts" rel="nofollow noreferrer">Generalised Abstract Data Types</a> (<code>GADTs</code>). </p> <pre><code>{-# Language GADTs, GADTSyntax #-} </code></pre> <p>We can put the context on the constructor directly, by providing an explict type signature:</p> <pre><code>data Tree a where EmptyTree :: (Ord a,Eq a) =&gt; Tree a Node :: (Ord a,Eq a) =&gt; a -&gt; Tree a -&gt; Tree a -&gt; Tree a </code></pre> <p>and then whenever we pattern match with <code>Node a left right</code> we get an implicit <code>(Ord a,Eq a)</code> context, just like you want, so we can start to define <code>treeInsert</code> like this:</p> <pre><code>treeInsert :: a -&gt; Tree a -&gt; Tree a treeInsert a EmptyTree = Node a EmptyTree EmptyTree treeInsert a (Node top left right) | a &lt; top = Node top (treeInsert a left) right | otherwise = Node top left (treeInsert a right) </code></pre> <h2>Deriving stuff</h2> <p>If you just add <code>deriving Show</code> there, you get an error:</p> <pre><code>Can't make a derived instance of `Show (Tree a)': Constructor `EmptyTree' must have a Haskell-98 type Constructor `Node' must have a Haskell-98 type Possible fix: use a standalone deriving declaration instead In the data type declaration for `Tree' </code></pre> <p>That's a pain, but like it says, if we add the <code>StandaloneDeriving</code> extension (<code>{-# Language GADTs, GADTSyntax, StandaloneDeriving #-}</code>) we can then do stuff like</p> <pre><code>deriving instance Show a =&gt; Show (Tree a) deriving instance Eq (Tree a) -- wow </code></pre> <p>and everything works out ok. The wow was because the implicit <code>Eq a</code> context means we don't need an explicit <code>Eq a</code> on the instance.</p> <h2>The context only comes from contstructors</h2> <p>Bear in mind that you only get the implicit context from using one of the constructors. (Remember that's where the context was defined.)</p> <p>This is actually why we needed the context on the <code>EmptyTree</code> constructor. If we'd just put <code>EmptyTree::Tree a</code>, the line</p> <pre><code>treeInsert a EmptyTree = Node a EmptyTree EmptyTree </code></pre> <p>wouldn't have an <code>(Ord a,Eq a)</code> context from the left hand side of the equation, so the instances would be missing from the right hand side, where they're needed for the <code>Node</code> constructor. That would be an error, so it's helpful in this case to keep the contexts consistent.</p> <p>This also means that you can't have</p> <pre><code>treeMake :: [a] -&gt; Tree a treeMake xs = foldr treeInsert EmptyTree xs </code></pre> <p>you'll get a <code>no instance for (Ord a)</code> error, because <em>there's no constructor on the left hand side to give you the <code>(Ord a,Eq a)</code> context</em>.</p> <p>That means you still need </p> <pre><code>treeMake :: Ord a =&gt; [a] -&gt; Tree a </code></pre> <p>There's no way round it this time, sorry, but on the plus side, this may well be the only tree function you'll want to write with no tree argument. <em>Most</em> tree functions will take a tree on the left hand side of the definition and do somthing to it, so you'll have the implicit context most of the time.</p>
    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