Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Use data and parameters, not existentials to get contexts</h2> <p>I think if you wanted</p> <pre><code>data Thing = Good [(Char,Int)] | Bad String | Indifferent Leg </code></pre> <p>but also sometimes</p> <pre><code>data Thing = Good [(Char,Float)] | Bad String | Indifferent Arm </code></pre> <p>You could define</p> <pre><code>data Thing num bodypart = Good [(Char,num)] | Bad String | Indifferent bodypart </code></pre> <p>or if you want to make sure <code>num</code> is always numeric, you could do</p> <pre><code>data Num num =&gt; Thing num bodypart = Good [(Char,num)] | Bad String | Indifferent bodypart </code></pre> <p>and finally, you could restrict the types allowed in <code>bodypart</code> by defining your own class:</p> <pre><code>class Body a where -- some useful function(s) here instance Body Leg where -- define useful function(s) on Legs instance Body Arm -- define useful function(s) on Arms data (Num num,Body bodypart) =&gt; Thing num bodypart = Good [(Char,num)] | Bad String | Indifferent bodypart </code></pre> <p>I'd like to discourage you from using existential types via the forall constructor or via GADTs because adding the <code>num</code> parameter to your data type is <em>considerably</em> more useful in practice, even though it takes more typing.</p> <h2>Constraints on type synonyms?</h2> <p>Note that when you use a constraint like </p> <pre><code>data (Num num) =&gt; Thing num = T [(Char,num)] </code></pre> <p>really only changes the type of the constructor <code>T</code> to </p> <pre><code>T :: (Num num) =&gt; [(Char,num)] -&gt; Thing num </code></pre> <p>instead of <code>T :: [(Char,num)] -&gt; Thing num</code>. This means every time you use <code>T</code>, there needs to be a context <code>(Num num)</code>, but that's really what you wanted - to stop people putting data in your data type that isn't numeric.</p> <p>A consequence of this fact is that you <em>can't</em> write</p> <pre><code>type Num num =&gt; [(Char,num)] </code></pre> <p>because there's no data constructor function <code>T</code> for the context <code>(Num num)</code> to be required on; if I have a [('4',False)], it automatically matches the type <code>[(Char,num)]</code> because it's a <em>synonym</em>. The compiler can't be going running around your code looking for instances before it decides what type something is. In the <code>data</code> case, it's got a constructor <code>T</code> that tells it the type, and it can guarantee there's a <code>Num num</code> instance because it checked your use of the function <code>T</code>. No <code>T</code>, no context.</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