Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 不带ScopedTypeVariables的外部绑定类型声明_Haskell - Fatal编程技术网

Haskell 不带ScopedTypeVariables的外部绑定类型声明

Haskell 不带ScopedTypeVariables的外部绑定类型声明,haskell,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

我有以下工作定义:

{-# 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
pragma的情况下重新实现它,或者我是否可以,以及
processError
的推断类型声明实际上是什么,因为指定
processError::IOException->IO a
会使其无法编译。

如果要避免
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

processError
的类型推断为

processError :: IOException -> IO a

此处的
a
重试的签名中的类型变量相同。但是,如果没有扩展名
ScopedTypeVariables
,则不能在Haskell中指定该类型,因为默认情况下,写下的签名中的类型变量是通用量化的。

另一个选项,可能比aTypeof更简洁:

retrying [] action = action 
retrying (i:is) action = catch action processError                                                                                                                                
  where
    processError e = threadDelay i >> retrying is action
      where
        _ = e :: IOException
不确定这是否是惯用语;我刚刚编造出来,效果很好。

这个怎么样:

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 a
的问题,其中
a
是泛型的,与封闭函数中的
a
不同,方法是在参数中加入类型为
a
的参数,以便将其绑定到封闭函数中的类型。

谢谢。但是
processError
的类型签名呢?它如何将
操作的类型绑定到外部函数?
processError
没有
ScopedTypeVariables
就不能有类型签名。在其推断类型中,使用封闭作用域数据中的
action
将其结果类型指定为
IO,无论重试的结果类型是什么。因此,给定
重试::[Int]>ioa->ioa
,推断出的
processError
类型是
processError::IOException->ioa
。但是没有STV你就写不下这种类型。出于好奇,lambda演算数学家会用什么花哨的名字来描述这种把戏?@Tarrasch我不知道它是否广泛到可以命名。我主要在quickcheck测试的上下文中看到过这种情况,在这里你可以看到成语
where\u types=(foo::a,bar::B)
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