Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is the <a href="http://www.haskell.org/haskellwiki/Scoped_type_variables" rel="nofollow noreferrer">Scoped Type Variables</a> GHC extension at work. Follow the link to learn more.</p> <p>Basically, you define an assertion about type that have to be met by the patter before it can match. So, yeah, it is akin to guards, but not completely so.</p> <p>How this particular example works? Dive into <a href="http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/src/Control-Exception-Base.html" rel="nofollow noreferrer">sources of "base" library</a> to find out that:</p> <pre><code>class (Show e) =&gt; Exception e where toException :: e -&gt; SomeException fromException :: SomeException -&gt; Maybe e data SomeException = forall e . Exception e =&gt; SomeException e instance Exception IOException where toException = IOException fromException (IOException e) = Just e fromException _ = Nothing instance Exception ArithException where toException = ArithException fromException (ArithException e) = Just e fromException _ = Nothing </code></pre> <p>We see that <code>IOException</code> and <code>ArithException</code> are different types implementing the typeclass <code>Exception</code>. We also see that <code>toException/fromException</code> is a wrapping/unwrapping mechanism that allows one to convert values of type <code>Exception</code> to/from values of types <code>IOException</code>, <code>ArithException</code>, etc.</p> <p>So, we could've written:</p> <pre><code>f = expr `catches` [Handler handleArith, Handler handleIO] handleArith :: ArithException -&gt; IO () handleArith ex = .... handleIO :: IOException -&gt; IO () handleIO ex = .... </code></pre> <p>Suppose that <code>IOException</code> happens. When <code>catchesHandler</code> processes first element of the handlers list, it calls <code>tryHandler</code>, which calls <code>fromException</code>. From the definition of <code>tryHandler</code> it follows that return type of the <code>fromException</code> should be the same as argument of <code>handleArith</code>. On the other hand, <code>e</code> is of type Exception, namely - (IOException ...). So, the types play out this way (this is not a valid haskell, but I hope that you get my point):</p> <pre><code>fromException :: (IOException ...) -&gt; Maybe ArithException </code></pre> <p>From the <code>instance Exception IOException ...</code> it follows immediately that the result is <code>Nothing</code>, so this handler is skipped. By the same reasoning the following handler would be called, because <code>fromException</code> would return <code>(Just (IOException ...))</code>.</p> <p>So, you've used type signatures of <code>handleArith</code> and <code>handleIO</code> to specify when each of them would be called, and <code>fromException/toException</code> made sure that it happened this way.</p> <p>If you want to, you could also constraint types of <code>handleIO</code> and <code>handleArith</code> inside the definition of <code>f</code>, using scoped type variables. Arguably, this could give you better readability.</p> <p>Finalizing, Scoped Type Variables are not a primary players here. They are just used for convenience. Main machinery for playing this kind of tricks is <code>fromException/toException</code> and friends. Scoped Type Variables just allow you to have syntax which more closely resemble guard patterns.</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