跳转至

柯里化和部分应用

柯里化 (Currying)

柯里化是将单个拥有多个参数的函数转变为多个拥有单个参数的函数.

柯里化可以解释 Haskell 以及其他函数式编程语言 (如 OCaml) 和命令式编程语言在语法上的一些区别:

  1. Haskell 的函数类型声明没有特别区分参数与返回值类型.
  2. Haskell 中调用函数不需要使用括号包裹参数.
min :: Ord a => a -> a -> a
min x y = if x <= y then x else y

关键字 ->1 用于构造函数参数. 该运算符是右结合的, 即上面的函数声明实际上是:

min :: Ord a => a -> (a -> a)

这表明 min 函数首先接受一个参数, 并返回一个函数, 该返回的函数再接受第二个参数. min 函数的完整应用过程如下:

min 1 2
=> (min 1) 2 -- Haskell 中的函数应用是左结合的
=> (\y -> if 1 <= y then 1 else y) 2
=> if 1 <= 2 then 1 else 2
=> 1

通过命令式语言实现 min 函数如下:

fn min<T: PartialOrd + Copy>(x: T) -> impl Fn(T) -> T {
    move |y| if x < y { x } else { y }
}

可以通过 min(1)(2) 对其进行调用. 完整代码.

部分应用 (Partial application)

得益于柯里化, Haskell 中的函数支持部分应用:

min 5
=> (\y -> if 5 <= y then 5 else y)
ghci> f = min 5
ghci> :t f
f :: (Ord a, Num a) => a -> a
ghci> f 3
3
ghci> f 7
5

与 C++ 中的 std::bind 相比, 部分应用不能跳过或对参数进行重新排序.

部分应用可以用于简化代码, 同时增加代码的可读性:

map (\x -> x * x) [1..]
map (^2) [1..]

评论