Note that there are some explanatory texts on larger screens.

plurals
  1. POEnforced pattern order
    primarykey
    data
    text
    <p>I'm writing a Magic The Gathering (MTG) game engine in Haskell.</p> <p>For those unfamiliar with MTG, it's a card game where cards can have up to 5 colors: White (W), Blue (U), Black (B), Red (R), and Green (G).</p> <pre><code>{-# LANGUAGE ViewPatterns #-} import Data.Set data Color = W | U | B | R | G deriving (Show, Eq, Ord) data Card = Card (Set Color) -- simplified Card type with only its colors viewColors :: Card -&gt; [Color] viewColors (Card colors) = toList colors </code></pre> <hr> <p>What I would like to do is pattern match on colors like so:</p> <pre><code>foo :: Card -&gt; String foo (viewColors -&gt; [W, B]) = "card is white and black" foo _ = "whatever" </code></pre> <p>So far, so good. But there is one problem here: I can type the order of colors incorrectly in the view pattern like so:</p> <pre><code>bar :: Card -&gt; String bar (viewColors -&gt; [B, W]) = "this will never get hit" bar _ = "whatever" </code></pre> <p>Of course, I could have written <code>viewColors</code> in a way that directly resolves this problem. Or I could use guards, but I'd rather not. Here are a couple ways to do so</p> <pre><code>viewColors :: Card -&gt; (Bool, Bool, Bool, Bool, Bool) viewColors (Card colors) = let m = (`member` colors) in (m W, m U, m B, m R, m G) </code></pre> <p>This solution is overly verbose while pattern matching, even if I use a type isomorphic to <code>Bool</code> but with shorter (and/or meaningful) identifiers. Matching a Green card would look like</p> <pre><code>baz :: Card -&gt; String baz (viewColors -&gt; (False, False, False, False, True)) = "it's green" </code></pre> <hr> <pre><code>data ColorView = W | WU | WUB | ... all combos here viewColors :: Card -&gt; ColorView viewColors (Card colors) = extract correct Colorview from colors </code></pre> <p>This solution has combinatorial explosion. Seems extremely bad to implement, but nice to use, especially if I have a <code>colorViewToList :: ColorView -&gt; [Color]</code> to allow programmatic extraction after the pattern match.</p> <hr> <p>I have no idea if the following can be approximated in Haskell, but the following would be ideal:</p> <pre><code>fuz :: Card -&gt; String fuz (viewColors -&gt; (W :* ())) = "it's white" fuz (viewColors -&gt; (W :* U :* ())) = "it's white and blue" fuz (viewColors -&gt; (W :* B :* ())) = "it's white and black" </code></pre> <hr> <p>I'm willing to use advanced language extensions to allow this kind of code: DataKinds, PolyKinds, TypeFamilies, MultiParamTypeClasses, GADTs, you name it.</p> <p>Is something like this possible? Do you have other suggested approaches?</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.
 

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