title: How to differentiate errors in Elixir's `with` macro?
body: <p>Often I have code that uses the <code>with</code> macro to ensure all the required data is available before proceeding, but I want to have more fine-grained errors to determine precisely why it failed.</p>
  
  <p>Using an example from the documentation:</p>
  
  <pre><code>with {:ok, width} &lt;- Map.fetch(opts, :width),
       {:ok, height} &lt;- Map.fetch(opts, :height) do
    {:ok, width * height}
  else
    :error -&gt;
      {:error, :wrong_data}
  end
  </code></pre>
  
  <p>I would like to know whether the <code>width</code> or the <code>height</code> is missing in the error tuple.</p>
  
  <p>My attempt is to use defaults:</p>
  
  <pre><code>with {:ok, width} &lt;- Map.fetch(opts, :width, {:error, :missing_width}),
       {:ok, height} &lt;- Map.fetch(opts, :height, {:error, :missing_height}) do
    {:ok, width * height}
  else
    {:error, reason} = error -&gt; error
  end
  </code></pre>
  
  <p>But this doesn't feel particularly elegant. Is there a more idiomatic way? </p>