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

时间:2015-01-29 09:20:49

标签: haskell

我通过阅读"了解你的Haskell for Great Goog来学习Haskell!" 一书。我想确保我正确地理解这是" currying"。

我理解一个函数不能获得多个参数。当函数具有多个参数时,实际作为具有一个参数的函数工作。即这样:

func :: Int -> Int -> Int -> Int

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

func :: Int -> (Int -> (Int -> Int))

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

参数多于零的任何函数都可以部分应用。即有可能告诉" currying"是"部分应用程序" 的动作反向。我是对的吗?

2 个答案:

答案 0 :(得分:7)

没有

反击是 uncurrying

f :: a -> b -> c

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

f'' :: a -> b -> c
f'' = -- curried f' = f

一个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

答案 1 :(得分: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

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

现在我们可以使用标准curryuncurry函数在二元函数的两个表示之间进行转换。在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

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

正如Bartek在答案中正确陈述的那样,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

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