我有以下工作定义:
{-# 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
Run Code Online (Sandbox Code Playgroud)
出于好奇,我想知道如何在不使用ScopedTypeVariablespragma的情况下重新实现这一点,或者我是否可以实现,以及实际推断的类型声明processError是什么,因为指定processError :: IOException -> IO a使其无法编译.
另一种选择,可能比asTypeOf更清洁:
retrying [] action = action
retrying (i:is) action = catch action processError
where
processError e = threadDelay i >> retrying is action
where
_ = e :: IOException
Run Code Online (Sandbox Code Playgroud)
不确定这是否是惯用的; 我刚刚完成它并且它有效.
如果你想避免ScopedTypeVariables,你可以在大多数时间使用asTypeOf.
retrying [] action = action
retrying (i:is) action = catch action processError
where
processError e = snd (e `asTypeOf` (undefined :: IOException), threadDelay i >> retrying is action)
Run Code Online (Sandbox Code Playgroud)
这undefined :: IOException是表达式类型签名,标准允许这样做.该asTypeOf要求的例外e是一个IOException.
不过,我更喜欢ScopedTypeVariables这里.
同
retrying :: [Int] -> IO a -> IO a
Run Code Online (Sandbox Code Playgroud)
processError推断的类型
processError :: IOException -> IO a
Run Code Online (Sandbox Code Playgroud)
用a在这里是相同类型的变量中的签名retrying.但是,在没有ScopedTypeVariables扩展名的情况下,不能在Haskell中指定该类型,因为写下签名中的类型变量默认是通用量化的.