没有ScopedTypeVariables的外部绑定类型声明

Nik*_*kov 4 haskell

我有以下工作定义:

{-# 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使其无法编译.

Ita*_*man 7

另一种选择,可能比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)

不确定这是否是惯用的; 我刚刚完成它并且它有效.


Dan*_*her 6

如果你想避免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中指定该类型,因为写下签名中的类型变量默认是通用量化的.