title: Modeling a domain as a GADT type and providing do-sugar for it
body: <p>Assume we'd like to build a type that represents operations typical for, let's say, a lock-free algorithm:</p>
  
  <pre class="lang-hs prettyprint-override"><code>newtype IntPtr = IntPtr { ptr :: Int } deriving (Eq, Ord, Show)
  
  data Op r where 
    OpRead :: IntPtr -&gt; Op Int
    OpWrite :: IntPtr -&gt; Int -&gt; Op ()
  
    OpCAS :: IntPtr -&gt; Int -&gt; Int -&gt; Op Bool
  </code></pre>
  
  <p>Ideally, we'd like to represent some algorithms within this model using a convenient <code>do</code>-notation, like (assuming corresponding <code>read = OpRead</code> and <code>cas = OpCAS</code> for aesthetic reasons) the following almost literal translation of the <a href="https://en.wikipedia.org/wiki/Compare-and-swap#Example_application:_atomic_adder" rel="nofollow noreferrer">Wikipedia example</a>:</p>
  
  <pre class="lang-hs prettyprint-override"><code>import Prelude hiding (read)
  import Control.Monad.Loops
  
  add :: IntPtr -&gt; Int -&gt; Op Int
  add p a = snd &lt;$&gt; do
    iterateUntil fst $ do
      value &lt;- read p
      success &lt;- cas p value (value + a)
      pure (success, value + a)
  </code></pre>
  
  <p>How could we achieve that? Let's add a couple more constructors to <code>Op</code> to represent pure injected values and the monadic bind:</p>
  
  <pre class="lang-hs prettyprint-override"><code>  OpPure :: a -&gt; Op a
    OpBind :: Op a -&gt; (a -&gt; Op b) -&gt; Op b
  </code></pre>
  
  <p>So let's try to write a <code>Functor</code> instance. <code>OpPure</code> and <code>OpBind</code> is easy, being, for instance:</p>
  
  <pre class="lang-hs prettyprint-override"><code>instance Functor Op where
    fmap f (OpPure x) = OpPure (f x)
  </code></pre>
  
  <p>But the constructors that specify the GADT type start smelling bad:</p>
  
  <pre class="lang-hs prettyprint-override"><code>  fmap f (OpRead ptr) = do
      val &lt;- OpRead ptr
      pure $ f val
  </code></pre>
  
  <p>Here we assume we'll write the <code>Monad</code> instance later on anyway to avoid ugly nested <code>OpBind</code>s.</p>
  
  <p>Is this the right way to handle such types, or is my design just terribly wrong, this being a sign of it?</p>