给Haskell中的函数提供太多参数

时间:2016-11-17 13:57:59

标签: haskell

在Haskell中,我可以给一个函数提供太少的参数来取回一个curried函数:

-- the addition function
Prelude> :t (+) 
(+) :: Num a => a -> a -> a

-- curried with its first argument => the increment function
Prelude> :t (+) 1
(+) 1 :: Num a => a -> a

-- supplied with both arguments => the result
Prelude> :t (+) 1 2
(+) 1 2 :: Num a => a

但是当我提供太多论据时我会得到什么?

Prelude> :t (+) 1 2 3
(+) 1 2 3 :: (Num a, Num (a -> t)) => t

这是什么,它有名称,对任何东西都有用吗?

2 个答案:

答案 0 :(得分:9)

以这种方式思考它是有用的。 总是为函数提供一个参数。 f a b完全等同于(f a) b

所以(+) 1 2 3

相同
 (((+) 1) 2) 3

现在我们知道((+) 1) 2是什么,它与(+) 1 21 + 2只是3相同。所以表达式归结为3 3

为什么它不是错误?

Haskell中的整数文字被重载。 3可以是任何类型,只要此类型具有Num实例。向函数类型提供Num实例也没有任何违法行为。类型推断器告诉你:

(Num a, Num (a -> t)) => t

这可以理解为

  

对于具有a实例的任何类型Num,以及也具有a->t实例的任何类型Num,相关表达式的类型为{{1} }。

当然在实践中这样的实例不太可能,但是一个可以原则上定义它们,并使表达式t评估为明确定义的值。

答案 1 :(得分:5)

一般来说,你只是得到一个错误,因为将一个函数应用到"足够"参数不会产生可以作为函数应用于另一个值的值。

> (++) [1] [2] [3]

<interactive>:1:1: error:
    • Couldn't match expected type ‘[Integer] -> t’
                  with actual type ‘[Integer]’
    • The function ‘(++)’ is applied to three arguments,
      but its type ‘[Integer] -> [Integer] -> [Integer]’ has only two
      In the expression: (++) [1] [2] [3]
      In an equation for ‘it’: it = (++) [1] [2] [3]
    • Relevant bindings include it :: t (bound at <interactive>:1:1)

但是,对于(+),返回值可以是任何类型,其实例为Num。由于(+) 1 2的类型为Num a => a,如果a -> t也有Num的实例,则可以假设(+) 1 2可以再次应用于 void test_func(char* bigarray) { std::vector<char> v_data; int len=strlen(bigarray); v_data.reserve(len); v_data.assign(bigarray,bigarray+len); } 第三个价值。这是一个类型类 open 的演示。