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

为Haskell中的函数提供太多参数,haskell,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 -- suppl

在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

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

通常,您只会得到一个错误,因为将一个函数应用到足够多的参数的结果不会产生一个可以作为函数应用到另一个值的值

> (++) [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可以再次应用于第三个值。这是一个类型类是开放的演示。

这样考虑是很有用的。你总是只给一个函数一个参数。fab与fab完全等价

所以+1 2 3与

 (((+) 1) 2) 3
现在我们知道+12是什么了,它和+12或1+2一样,也就是3。所以这个表达式可以归结为3

为什么这不是一个错误

Haskell中的整数文本被重载。3可以是任何类型,前提是此类型具有Num实例。将Num实例赋予函数类型也没有什么非法的。类型推断器告诉您:

(Num a, Num (a -> t)) => t
这可以理解为

对于具有Num实例的任何类型a,以及也具有Num实例的任何类型a->t,所讨论的表达式具有类型t


当然,在实践中不太可能出现这种情况,但原则上可以定义它们,并使表达式+1 2 3计算为一个定义良好的值。

可能重复,因此我遇到了这种情况,因为数字文字仍然灵活,可以解释为Num的不同实例,就类型检查器而言,1不仅可以作为Int或分数,还可以作为a->t?我试图强制参数为Int而不是Num a,然后它立即产生了一个错误:let one=1::Int:t+one->type error我明白了。因此,理论上有人可以为Num a创建一个Num a->t的实例,然后您希望+x y z检查这种类型的值。理论上,即使对于文本也可以这样做吗?有没有一种方法可以增强数值文本的解释,使1可以成为函数值或编译器内置的转换以外的任何其他值?是的,拥有Num实例意味着您可以对类型使用整数文本。这是由fromInteger方法处理的。所以3实际上是一个fromInteger 3::Integer。你可以为你的实例写fromInteger,这样你就可以得到3,比如const3。