2

在什么情况下可以f :: a -> b -> c -> d定义函数

f w x y z = ...

我不会认为这是可能的,但在查看enumerator包裹时,我发现:

enumFileRange :: FilePath
              -> Maybe Integer -- ^ Offset
              -> Maybe Integer -- ^ Maximum count
              -> Enumerator B.ByteString IO b
enumFileRange path offset count step = do
    h <- tryIO (IO.openBinaryFile path IO.ReadMode)
    let iter = enumHandleRange 4096 offset count h step
    Iteratee (Exc.finally (runIteratee iter) (IO.hClose h))

资源

显然我们有一个三个参数的函数,它是通过传入四个参数来实现的。同样,签名enumHandleRange

enumHandleRange :: MonadIO m
                => Integer -- ^ Buffer size
                -> Maybe Integer -- ^ Offset
                -> Maybe Integer -- ^ Maximum count
                -> IO.Handle
                -> Enumerator B.ByteString m b

表示它有四个参数,但我们在enumFileRange上面通过传入五个参数来调用它:let iter = enumHandleRange 4096 offset count h step.

有人知道这是如何工作的吗?

4

2 回答 2

12

Enumerator是函数类型的类型同义词(类似于typedefC 中的 a):

type Enumerator a m b = Step a m b -> Iteratee a m b

所以enumFileRange实际上有以下类型:

enumFileRange :: FilePath
              -> Maybe Integer -- ^ Offset
              -> Maybe Integer -- ^ Maximum count
              -> Step B.ByteString IO b
              -> Iteratee B.ByteString IO b
于 2013-10-29T10:11:38.390 回答
1

Haskell 中的所有函数都有表单的签名a -> b。如果函数有“多个参数”,这仅仅意味着b它又是一个函数类型。所以,回答

在什么情况下函数 f :: a -> b -> c -> d 可以定义为

f w x y z = ...

答案是always,因为无约束类型变量 likea, b, c, d总是可以解析为函数类型。事实上,即使类型类约束与函数“明显不兼容”,类型检查器最初也会假设这一点,这就是为什么我们有时会收到如此有趣的错误消息,例如

GHCi,版本 7.6.2:http ://www.haskell.org/ghc/   :? 寻求帮助
加载包 ghc-prim ... 链接 ... 完成。
加载包 integer-gmp ... 链接 ... 完成。
正在加载包库...链接...完成。
Prelude> 7 "x"

<‌interactive‌>:2:1:
    (Num ([Char] -> t0)) 没有由文字 `7' 引起
    的实例可能的修复:为 (Num ([Char] - > t0))
    在表达式中:7
    在表达式中:7 "x"
    在 `it' 的等式中:it = 7 "x"

对于诸如此类的固定类型Enumerator B.ByteString IO b是不正确的。在这种情况下,您是否真的有必要处理函数类型的 typedef,就像 rightfold 所说的那样Enumerator

于 2013-10-29T10:22:37.250 回答