Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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 未成熟函数的类型签名_Haskell - Fatal编程技术网

Haskell 未成熟函数的类型签名

Haskell 未成熟函数的类型签名,haskell,Haskell,uncurry将当前函数转换为成对函数,但上面的函数仅将其转换为当前函数f a b。这是否与uncurry函数的定义相矛盾?我认为你误读了。它确实会返回成对的函数。这就是\(a,b)->部分的意思-它定义了一个匿名函数,它接受一对值,并对该对中的值执行给定的函数。编写此定义的另一种方法,以便更清楚地了解发生了什么: uncurry f=\(a,b)->f a b 变量f的类型为a->b->c,即它是一个curried函数,而uncurry g对于某些curried函数g的类型为(a,b)

uncurry
将当前函数转换为成对函数,但上面的函数仅将其转换为当前函数
f a b
。这是否与
uncurry
函数的定义相矛盾?

我认为你误读了。它确实会返回成对的函数。这就是
\(a,b)->
部分的意思-它定义了一个匿名函数,它接受一对值,并对该对中的值执行给定的函数。

编写此定义的另一种方法,以便更清楚地了解发生了什么:

uncurry f=\(a,b)->f a b
变量
f
的类型为
a->b->c
,即它是一个curried函数,而
uncurry g
对于某些curried函数
g
的类型为
(a,b)->c
,即一个uncurried函数


请记住,当
x
y
是术语时,
xy
表示将函数
x
应用于
y
。而
fab
(或
(fa)b
)意味着将函数
f
应用于参数
a
,生成类型为
b->c
的函数,然后立即将此函数应用于
b
,生成类型为
c
的结果。因此,这个定义的右侧只是展示了如何解包元组参数的组件,并将它们应用到一个curry函数,这正是一个不修剪的过程

pelotom和Chuck所说的百分之百正确。我想你只是在某些时候对curry vs uncurry和函数定义有点困惑


我们知道,curried函数类似于:

addxy=x+y

它的定义是:

uncurry f=\(a,b)->f a b
add::(Num a)=>a->a->a

Add接受一个
Num
,并返回一个函数,该函数接受一个
Num
并返回一个
Num

uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f = \(a, b) -> (f a) b
通过这种方式,我们可以得到一个部分应用的函数,如

add3=add3

由于使用了
add
,当我们只传递一个参数(在本例中为3)时,我们可以返回一个函数,该函数接受
Num
并返回
Num

uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f = \(a, b) -> (f a) b
未传递的函数接受元组,或将值分组在一起,如(1,2)。(注意,元组不必成对。您可以有一个(1,2,3,4,5)形式的元组。只有常规的old uncurry处理特定的成对)。如果我们将add更改为uncarried,则会是:

>add3 5
8
它接受两个
Num
s的元组并返回一个Num。我们不能像将add作为curried函数那样部分应用它。它需要两个参数,以元组形式传递

现在,转到uncurry函数!(如果您想知道函数的类型,请在GHCi中使用
:t
,或使用)

那么我们从中了解到了什么?它采用f,我们从定义中注意到,它是(a->b->c)中的curried函数,并且它返回未加载波的函数((a,b)->c)

如果我们不加修改地输入我们的咖喱add(记住:
addxy
),我们会得到什么

我们得到一个匿名函数,或lambda函数,它接受一个元组,并将元组
a
b
的值应用到我们的函数
add

fab
并不意味着我们得到一个函数——如果是这样的话,你会看到一个
->
。我们只需通过
a
b
获得
f

这有点像是我们用手做的:

tupleAdd(a,b)=添加b

但是,
uncurry
为我们做了这一切,我们可以继续使用我们最初使用的函数的全新uncurry形式


酷毙了,嗯?

您可以编写一个没有lambda的函数,其行为方式相同(并且具有相同的签名):

uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry f=\(a,b)->f a b
我认为这个版本更容易阅读。如果您有一个元组和一个接受两个单一值的函数(或者更确切地说,它接受一个值并返回一个接受下一个值的函数),uncurry'函数为我们执行元组的“展开”

一般来说,如果你看到

uncurry' :: (a -> b -> c) -> ((a, b) -> c)
uncurry' f (a,b) = f a b
这和

f x y z = x + y + z

f x = \y -> (\z -> x + y + z)