Haskell 带有函数参数的函数是否已被咖喱化?

Haskell 带有函数参数的函数是否已被咖喱化?,haskell,functional-programming,currying,Haskell,Functional Programming,Currying,从 在哈斯克尔,一切都是咖喱;所有函数都只接受一个参数,甚至Haskell中的未终止函数也接受一个元组,严格来说,这是一个参数-您可能需要使用curry和uncurry函数来了解它是如何工作的 我不确定这是不是真的,但假设是这样 如果一个函数将另一个函数作为参数,那么它是curried还是uncarried,其意义与将元组或列表参数作为uncarried的函数相似?成对元组类型是type1 x type2,可以是type1^2,而函数类型是type2^{type1},所以我发现它们很相似 如果未

在哈斯克尔,一切都是咖喱;所有函数都只接受一个参数,甚至Haskell中的未终止函数也接受一个元组,严格来说,这是一个参数-您可能需要使用curry和uncurry函数来了解它是如何工作的

我不确定这是不是真的,但假设是这样

如果一个函数将另一个函数作为参数,那么它是curried还是uncarried,其意义与将元组或列表参数作为uncarried的函数相似?成对元组类型是type1 x type2,可以是type1^2,而函数类型是type2^{type1},所以我发现它们很相似

如果未编译,如何将此类函数转换为curried函数

如果一个函数以另一个函数作为参数,它是curried还是uncurried

它只需要一个函数,所以只有一个参数,因此它是curry。该参数是函数这一事实与此无关

例如,这样的函数是map。地图具有以下类型:

map :: (a -> b) -> ([a] -> [b])
因此,它只接受一个参数,即类型a->b的函数,然后返回一个函数[a]->[b],该函数将通过应用该函数将as列表映射到bs列表

所以map show::show a=>[a]->[String]是这种函数应用的结果,这也是一个函数

如果一个函数以另一个函数作为参数,它是curried还是uncurried

它只需要一个函数,所以只有一个参数,因此它是curry。该参数是函数这一事实与此无关

例如,这样的函数是map。地图具有以下类型:

map :: (a -> b) -> ([a] -> [b])
因此,它只接受一个参数,即类型a->b的函数,然后返回一个函数[a]->[b],该函数将通过应用该函数将as列表映射到bs列表


所以map show::show a=>[a]->[String]是这种函数应用的结果,这也是一个函数。

是的,引号是正确的。所有关于curried和uncarried函数的讨论都是不精确的行话

哈斯凯尔语是一种咖喱语。Haskell中的函数总是具有指数类型。如果一个参数是一个元组,那没关系,它仍然只是一个碰巧是元组的值

当我们将a,b->c Haskell函数视为c a*b函数时,这些概念是近似的。但这只是我们做的心理体操

不管是不是咖喱,都是编程语言。例如,在Lisp中

(lambda (a b) c)
实际上是c a*b类型,要将其转换为c ba函数,我们需要对其进行一些转换

Haskell中实际上没有\a b->c lambda,只有\a->\b->c嵌套lambda*。当我们在Haskell中编写\ab->c时,它只是\a->\b->c的一个语法快捷方式。在Haskell中不可能有实际的\a b->c lambda函数,尽管它近似于\a,b->c lambda函数

当您使用lambda函数实现自己的语言时,您真正理解了所有这些的意义

面对lambda a b c x y z函数调用,真正的问题是如何将函数的参数与提供的值配对

Haskell将其转换为Cz中的let a=x,但Lisp实际上将参数列表a b与值列表x y z配对,并报告长度不匹配

但是,作为一种无载波语言,Lisp能够在这里进行各种扭曲和调整,如可选参数、默认参数、命名参数等,以各种不同的方式将参数和值配对-不像Haskell,它总是一次将一个参数与一个提供的值配对


*还有另一个重要区别:Haskell的\a->\b->c中的a和b不是变量,而是模式。它们不只是像Lisp中那样被赋值,而是与之匹配

是的,报价是正确的。所有关于curried和uncarried函数的讨论都是不精确的行话

哈斯凯尔语是一种咖喱语。Haskell中的函数总是具有指数类型。如果一个参数是一个元组,那没关系,它仍然只是一个碰巧是元组的值

当我们将a,b->c Haskell函数视为c a*b函数时,这些概念是近似的。但这只是我们做的心理体操

不管是不是咖喱,都是编程语言。例如,在Lisp中

(lambda (a b) c)
实际上是c a*b类型,要将其转换为c ba函数,我们需要对其进行一些转换

Haskell中实际上没有\a b->c lambda,只有\a->\b->c嵌套lambda*。当我们在Haskell中编写\ab->c时,它只是\a->\b->c的一个语法快捷方式。在Haskell中不可能有实际的\a b->c lambda函数,尽管它近似于\a,b->c lambda函数

当您使用lambda函数实现自己的语言时,您真正理解了所有这些的意义

面对一只羔羊 c x y z函数调用,真正的问题是如何将函数的参数与提供的值配对

Haskell将其转换为Cz中的let a=x,但Lisp实际上将参数列表a b与值列表x y z配对,并报告长度不匹配

但是,作为一种无载波语言,Lisp能够在这里进行各种扭曲和调整,如可选参数、默认参数、命名参数等,以各种不同的方式将参数和值配对-不像Haskell,它总是一次将一个参数与一个提供的值配对


*还有另一个重要区别:Haskell的\a->\b->c中的a和b不是变量,而是模式。它们不只是像Lisp中那样被赋值,而是与之匹配

至少我能看到的事实是,haskell中的几乎每个值都可以看作一个函数,每个函数每次只取一个参数。让我们看一个以Int为例的例子,更清楚地说:

f :: Int -> Int -> Int -> Int
f x y z = x + y + z
f可以看作是一个接受Int并返回函数的函数

Int -> (Int -> Int)


:t (f 2)
(f 2) :: Int -> Int -> Int
:t (f 2 3)
(f 2 3) :: Int -> Int
f2 3可以被看作是一个接受一个Int并返回一个Int的函数

最后

:t (f 2 3 4)
(f 2 3 4) :: Int
高阶函数示例:

h :: (Int -> Int -> Int) -> Int -> Int -> Int
h fn x y = fn x y
稍微复杂一点,但想法是一样的:

:t (h f)
(h f) :: Int -> Int -> Int -> Int
而f->Int->returning是一个函数

但是。。。等等,它不是期望返回一个函数吗?应该如此

(h f) :: Int -> Int -> (Int -> Int)
好吧,我提出了一个观点。让我们继续

:t (h f 2)
(h f 2) :: Int -> Int -> Int
HF2是一个需要Int并返回Int->Int函数的函数

最后

 :t (h f 2 3)
(h f 2 3) :: Int -> Int
HF23实际上是一个函数,期望一个Int,返回一个Int


我认为这里的结论是,.

至少我能看到的事实是,haskell中的几乎每个值都可以被视为一个函数,每个函数每次只取一个参数。让我们看一个以Int为例的例子,更清楚地说:

f :: Int -> Int -> Int -> Int
f x y z = x + y + z
f可以看作是一个接受Int并返回函数的函数

Int -> (Int -> Int)


:t (f 2)
(f 2) :: Int -> Int -> Int
:t (f 2 3)
(f 2 3) :: Int -> Int
f2 3可以被看作是一个接受一个Int并返回一个Int的函数

最后

:t (f 2 3 4)
(f 2 3 4) :: Int
高阶函数示例:

h :: (Int -> Int -> Int) -> Int -> Int -> Int
h fn x y = fn x y
稍微复杂一点,但想法是一样的:

:t (h f)
(h f) :: Int -> Int -> Int -> Int
HF是一个函数,预期为Int,返回Int->Int->Int->Int

但是。。。等等,它不是期望返回一个函数吗?应该如此

(h f) :: Int -> Int -> (Int -> Int)
好吧,我提出了一个观点。让我们继续

:t (h f 2)
(h f 2) :: Int -> Int -> Int
HF2是一个需要Int并返回Int->Int函数的函数

最后

 :t (h f 2 3)
(h f 2 3) :: Int -> Int
HF23实际上是一个函数,期望一个Int,返回一个Int


我认为这里的结论是,.

函数只是一个可以作为参数的值。假设一个函数使用另一个函数作为参数,如果该函数不使用多个值,那么咖喱化就无关紧要了?!我发现他们很相似,但事实并非如此。真的不是。咖喱实际上是关于a->b->c类型和a,b->c类型之间的同构。curried表单更方便,因为它允许更简单地使用部分应用程序,并且扩展性更好。咖喱/未咖喱同构本身不会将a->b->c->d类型的东西转换为a,b,c->d类型的东西;它只能给你a、b、c->d类型的东西。你需要第二个同构来将a,b,c展平到a,b,c。。。。虽然函数类型是type2^{type1}no,但区别在于type3^type1 x type2和type3^type2^type1。如何转换为curried函数。如果f是非载波的,则curry f是curry。函数只是一个可以作为参数的值。假设一个函数使用另一个函数作为参数,如果该函数不使用多个值,那么咖喱化就无关紧要了?!我发现他们很相似,但事实并非如此。真的不是。咖喱实际上是关于a->b->c类型和a,b->c类型之间的同构。curried表单更方便,因为它允许更简单地使用部分应用程序,并且扩展性更好。咖喱/未咖喱同构本身不会将a->b->c->d类型的东西转换为a,b,c->d类型的东西;它只能给你a、b、c->d类型的东西。你需要第二个同构来将a,b,c展平到a,b,c。。。。虽然函数类型是type2^{type1}no,但区别在于type3^type1 x type2和type3^type2^type1。如何转换为curried函数。如果f没有结婚,那么咖喱f就是咖喱。谢谢。它的uncarried是否与接受未连接的元组或列表参数的函数具有类似的意义?如果没有载波,如何将这样的函数转换为当前函数?@Tim No。函数是单个值。元组或列表由多个值组成,这是我们调用Haskell函数uncarried的唯一原因。谢谢。它的uncarried是否与接受未连接的元组或列表参数的函数具有类似的意义?如果没有载波,如何将这样的函数转换为当前函数?@Tim No。函数是单个值。元组或列表由多个值组成,这是唯一的
我们将Haskell函数称为uncarried函数的原因。1尽管这在很大程度上是正确的,但我认为应该在无参数的情况下划一条线。最终,Haskell函数的类型是->的,因此3::Int不是函数。另见。我建议从这个答案中删除这个案例。2接受的数值a不完全准确,因为数值a不是类型。以a作为Num的实例更好。3在一个相关的注释中,让f单态表示,f::Int->Int->Int->Int->Int将使您的示例更简单。@duplode非常感谢,我认为现在更清楚了,我接受了您的建议1虽然这基本上是正确的,但我相信应该在无参数的情况下划一条线。最终,Haskell函数的类型是->的,因此3::Int不是函数。另见。我建议从这个案例中删除答案。2接受的数值a不完全准确,因为数值a不是类型。以a作为Num的实例更好。3在一个相关的注释中,让f单态表示,f::Int->Int->Int->Int->Int将使您的示例更简单。@duplode非常感谢,我认为现在更清楚了,我接受了您的建议