是否有可能告诉"currying"是"部分应用"的反向行为?

And*_*man 2 haskell

我通过阅读"为了Goog而学习你的Haskell"来学习Haskell!书.我想确定我正确地理解这是"讨好".

我理解一个函数不能得到一个以上的参数.当一个函数有一个以上的参数时,它实际上是一个带有一个参数的函数.即:

func :: Int -> Int -> Int -> Int
Run Code Online (Sandbox Code Playgroud)

像这样工作(并且是相同的):

func :: Int -> (Int -> (Int -> Int))
Run Code Online (Sandbox Code Playgroud)

即一个函数返回一个函数,它也返回一个函数,等等.这个"嵌套娃娃"行为被称为"currying"(curried函数).代码的第一个变体就像是"语法糖".

可以部分应用具有多于零参数的任何函数.也就是说,可以说"currying"是"部分应用"的反向动作.我对吗?

Bar*_*icz 7

没有.

与咖喱相反的是反复的.

f :: a -> b -> c

f' :: (a, b) -> c
f' = -- uncurried f

f'' :: a -> b -> c
f'' = -- curried f' = f
Run Code Online (Sandbox Code Playgroud)

一个curried函数,尽管它的"语言"arity减少到1,保持"语义"arity不变(因为你仍然必须为元组提供每个值).比较中唯一改变的是传递参数的方式.

部分应用程序是将函数的arity减少到大于0的数字的应用程序.这是一个不可逆转的操作; 你无法不应用参数.

--   1    2
f :: a -> b -> c

--    1
f' :: b -> c
f' = f c -- partially applied f

--     0 arguments
f'' :: c
f'' = f c1 c2 -- fully applied f
Run Code Online (Sandbox Code Playgroud)

  • @Bush问题是"*正在讨论部分申请的反向*",答案是*no*. (3认同)
  • 它应该是`f'::(a,a) - > a`.但是最好使用不同的类型变量`a,b,c`:`f :: a - > b - > c`和`f'::(a,b) - > c`.另外`f'`实际上是*uncurried*,如`uncurry ::(a - > b - > c) - >(a,b) - > c`.我有麻烦要记住我自己也是哪种方式. (2认同)

Tox*_*ris 5

也就是说,可以说"currying"是"部分应用"的反向动作.

差不多但反过来说:"Currying"可以看作与"部分应用" 相同的东西.

让我在ghci会议的帮助下解释一下.我们首先为不同类型的函数定义一些类型的同义词.

Prelude> type Binary a b c = (a, b) -> c
Prelude> type Curried a b c = a -> (b -> c)
Prelude> type Unary a b = a -> b
Run Code Online (Sandbox Code Playgroud)

在这里,我们有两种表示二元函数的方法:我们有Binary像数学一样的函数,即接受元组的函数.然后我们Curried通常在Haskell中使用函数,即返回函数的函数.为了完整起见,我们还有一个特殊的Unary功能名称.

现在我们可以使用标准curry和uncurry函数在二元函数的两个表示之间进行转换.在ghci中,我们可以检查如下:

Prelude> :t curry :: Binary a b c -> Curried a b c
curry :: Binary a b c -> Curried a b c
  :: Binary a b c -> Curried a b c

Prelude> :t uncurry :: Curried a b c -> Binary a b c
uncurry :: Curried a b c -> Binary a b c
  :: Curried a b c -> Binary a b c
Run Code Online (Sandbox Code Playgroud)

(注意,当你输入时:t foo :: SomeType,ghci会检查是否foo有类型SomeType.如果是,ghci将再次打印.如果没有,ghci会抱怨).

因此,作为鲍尔泰克正确他的回答指出,逆curry是uncurry.但我们也可以理解curry如下类型:

Prelude> :t curry :: Binary a b c -> a -> Unary b c
curry :: Binary a b c -> a -> Unary b c
  :: Binary a b c -> a -> Unary b c
Run Code Online (Sandbox Code Playgroud)

如果我们写这样的类型,我们看到我们可以curry用来部分应用一个Binary函数:给定一个f :: Binary a b c和第一个参数,x :: a我们可以curry f x用来产生一个Unary b c仍然在等待类型的第二个参数b.