4

私は次の実用的な定義を持っています:

{-# 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

好奇心から、ScopedTypeVariablesプラグマを使用せずにこれを再実装するにはどうすればよいのか、まったくできないのか、そしてprocessError指定するとコンパイルできなくなるため、推論された型宣言は実際には何なのか疑問に思いますprocessError :: IOException -> IO a

4

3 に答える 3

7

別のオプション、おそらくasTypeOfよりも少しクリーンです:

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

これが慣用的なものかどうかはわかりません。私はちょうどそれを作りました、そしてそれは働きました。

于 2012-12-11T22:01:22.960 に答える
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)

これundefined :: IOExceptionは式タイプの署名であり、標準で許可されています。はasTypeOf、例外eがである必要がありIOExceptionます。

しかし、私はここを好みScopedTypeVariablesます。

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

のタイプは次のprocessErrorように推測されます

processError :: IOException -> IO a

ここでaは、のシグニチャと同じ型変数ですretryingScopedTypeVariablesただし、書き留められた署名の型変数はデフォルトで全称記号であるため、その型は拡張子なしでHaskellで指定することはできません。

于 2012-12-11T21:25:44.637 に答える
2

これはどう:

retrying [] action = action 
retrying (i:is) action = catch action $ processError $
                         threadDelay i >> retrying is action
  where
    processError :: IO a -> IOException -> IO a
    processError foo e = foo

基本的に、これはprocessError :: IOException -> IO aaが一般的であり、囲んでいる関数と同じではない場合に、囲んでいる関数の型に結び付けるためにa型を含む引数を取ることによって、を行う問題を処理します。a

于 2012-12-12T08:08:31.637 に答える