通过传入n + 1个参数来定义n个参数的函数?

时间:2013-10-29 10:09:53

标签: haskell iterate

在什么情况下可以通过

定义函数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))

Source

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

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

表示它有四个参数,但是我们通过传入五个参数enumFileRangelet iter = enumHandleRange 4096 offset count h step中调用它。

有人知道这是如何工作的,以及一般性如何?

2 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:1)

Haskell中的所有函数都有a -> b 形式的签名。如果函数具有“多个参数”,则这仅仅意味着b恰好是函数类型。所以,回答

  

在什么情况下函数f :: a - &gt; b - &gt; c - &gt; d由

定义
f w x y z = ...

答案将始终,因为像a, b, c, d这样的无约束类型变量总是可以解析为函数类型。实际上,即使类型类约束与函数“明显不兼容”,类型检查器也会首先假设这一点,这就是为什么我们有时会得到如此有趣的错误消息,如

  

GHCi,版本7.6.2:http://www.haskell.org/ghc/ :?寻求帮助
  加载包ghc-prim ...链接...完成。
  加载包integer-gmp ...链接...完成。
  加载包基...链接...完成。
  前奏&GT; 7“x”
  
  &LT;互动&GT;:2:1:
  没有(Num([Char] - > t0))的实例来自文字“7”   可能的解决方法:为(Num([Char] - &gt; t0))添加实例声明   在表达式中:7
  在表达式中:7“x”
  在'it'的等式中:it = 7“x”

对于Enumerator B.ByteString IO b等固定类型,这不是真的。在这种情况下,你是否真的有必要处理一个函数类型的typedef,就像Enumerator所说的rightfold一样。