Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Outer bound type declarations without ScopedTypeVariables

Tags:

haskell

I have a following working definition:

{-# LANGUAGE ScopedTypeVariables #-}
module Control.Retry where

import Prelude hiding (catch)
import Control.Exception
import Control.Concurrent

retrying [] action = action 
retrying (i:is) action = catch action processError
  where 
    processError (e :: IOException) = threadDelay i >> retrying is action

Just out of curiosity I am wondering how I could reimplement this without utilizing the ScopedTypeVariables pragma, or whether I could at all, and what the inferred type declaration of processError actually is, because specifying processError :: IOException -> IO a makes it uncompilable.

like image 713
Nikita Volkov Avatar asked Dec 06 '22 10:12

Nikita Volkov


2 Answers

Another option, maybe a little cleaner than asTypeOf:

retrying [] action = action 
retrying (i:is) action = catch action processError                                                                                                                                
  where
    processError e = threadDelay i >> retrying is action
      where
        _ = e :: IOException

Not sure if this is idiomatic; I just made it up and it worked.

like image 78
Itai Zukerman Avatar answered Dec 09 '22 14:12

Itai Zukerman


If you want to avoid ScopedTypeVariables, you can most of the time use asTypeOf.

retrying [] action = action 
retrying (i:is) action = catch action processError
  where 
    processError e = snd (e `asTypeOf` (undefined :: IOException), threadDelay i >> retrying is action)

The undefined :: IOException is an expression type signature, and that is allowed by the standard. The asTypeOf requires the exception e to be an IOException.

I would prefer ScopedTypeVariables here, though.

With

retrying :: [Int] -> IO a -> IO a

the type of processError is inferred as

processError :: IOException -> IO a

with the a here being the same type variable as in the signature of retrying. That type can, however, not be specified in Haskell without the ScopedTypeVariables extension, since type variables in written-down signatures are by default universally quantified.

like image 42
Daniel Fischer Avatar answered Dec 09 '22 15:12

Daniel Fischer