是否可以说 "currying" 是 "partial application" 的反向动作?
Is it possible to tell that the "currying" is an action reverse of the "partial application"?
我通过阅读"Learn You a Haskell for Great Goog!"这本书来学习Haskell。我想确定我正确理解了 "currying".
我了解一个函数不能获得超过一个参数。当一个函数有一个以上的参数时,它 实际上 就像一个只有一个参数的函数一样工作。 IE。这个:
func :: Int -> Int -> Int -> Int
像这样工作(并且是一样的):
func :: Int -> (Int -> (Int -> Int))
即一个函数 returns 一个函数,那个 returns 也是一个函数,等等。这种 "nested doll" 行为称为 "currying"(柯里化函数)。代码的第一个变体就像 "syntax sugar".
任何参数大于零的函数都可以部分应用。 IE。可以看出 "currying" 是 "partial application" 的反向动作。我说得对吗?
没有
柯里化的反面是非柯里化。
f :: a -> b -> c
f' :: (a, b) -> c
f' = -- uncurried f
f'' :: a -> b -> c
f'' = -- curried f' = f
柯里化函数,尽管它的 "language" 数量减少到 1,但保持 "semantic" 数量不变(因为您仍然必须为元组提供每个值)。比较中唯一改变的是你传递参数的方式。
部分应用是将函数的元数减少到大于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
I.e. it is possible to tell that the "currying" is an action reverse of the "partial application".
几乎相反:"Currying" 可以看作 与 "partial application" 相同的东西。
让我借助 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
数学中的函数,即接受元组的函数。然后我们有 Curried
函数,就像通常在 Haskell 中一样,也就是说,函数 return 一个函数。为了完整起见,我们还为 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
(注意,当你输入: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
.
的第二个参数
我通过阅读"Learn You a Haskell for Great Goog!"这本书来学习Haskell。我想确定我正确理解了 "currying".
我了解一个函数不能获得超过一个参数。当一个函数有一个以上的参数时,它 实际上 就像一个只有一个参数的函数一样工作。 IE。这个:
func :: Int -> Int -> Int -> Int
像这样工作(并且是一样的):
func :: Int -> (Int -> (Int -> Int))
即一个函数 returns 一个函数,那个 returns 也是一个函数,等等。这种 "nested doll" 行为称为 "currying"(柯里化函数)。代码的第一个变体就像 "syntax sugar".
任何参数大于零的函数都可以部分应用。 IE。可以看出 "currying" 是 "partial application" 的反向动作。我说得对吗?
没有
柯里化的反面是非柯里化。
f :: a -> b -> c
f' :: (a, b) -> c
f' = -- uncurried f
f'' :: a -> b -> c
f'' = -- curried f' = f
柯里化函数,尽管它的 "language" 数量减少到 1,但保持 "semantic" 数量不变(因为您仍然必须为元组提供每个值)。比较中唯一改变的是你传递参数的方式。
部分应用是将函数的元数减少到大于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
I.e. it is possible to tell that the "currying" is an action reverse of the "partial application".
几乎相反:"Currying" 可以看作 与 "partial application" 相同的东西。
让我借助 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
数学中的函数,即接受元组的函数。然后我们有 Curried
函数,就像通常在 Haskell 中一样,也就是说,函数 return 一个函数。为了完整起见,我们还为 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
(注意,当你输入: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
.