首页 > 解决方案 > Haskell - 过滤器,柯里化

问题描述

我只想知道我对柯里化函数的以下理解是否正确。我想要filter列表中的所有元素> 4。我可以这样实现:

filter (>4) [1..10]
  1. (>)被定义为Ord a => a -> a -> Bool,这就是为什么它不能被过滤。
  2. (>4)定义为(Ord a, Num a) => a -> Bool。该函数(>)现在被柯里化了,并且仍然需要一个参数。
  3. 因为2.,(>4)可以传递给过滤器。
  4. 每个传递给 filter 的 List-Element 都将传递给(>4)and 并且 filter 将验证谓词并返回结果。

它是否正确?

标签: haskellfilterfunctional-programmingcurrying

解决方案


推理或多或少是正确的。(>)是一个带有签名的函数:

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

所以它是一个函数(就像 Haskell 中的任何其他函数一样)接受一个参数,在这里返回一个 function a -> Bool

因此问题是,如果我们要使用filter (>) [1,4,2,5],那么我们将进行调用(>) 1,这将因此返回一个函数a -> Bool,但 afilter不能使用它,它需要一个从列表中获取元素并返回 a 的函数,而Bool不是返回映射到 a 的函数的函数Bool

因此,我们可以例如使用:

filter ((<) 4) [1,4,2,5]

因此,我们在这里执行该函数的部分应用[Haskell-wiki]。因此,这意味着我们生成了一个函数(<) 4 :: (Num a, Ord a) => a -> Bool。因此,我们可以使用该函数进行过滤,因此它将返回[5].

我们还可以使用 lambda 表达式创建一个函数来“交换”参数的顺序:

filter (\x -> (>) x 4) [1,4,2,5]

x在这里,我们将调用一个值,((>) x) 4这将返回一个Bool

由于经常会为中缀运算符的两侧之一提供一个值,因此 Haskell为中缀运算符 [Haskell-wiki] 提供了分段语法

  • (2^)左部分)等价于(^) 2,或更冗长\x -> 2 ^ x
  • (^2)(右 部分) 等价于flip (^) 2, 或更详细\x -> x ^ 2

所以我们可以将最后一个表达式重写为:

filter (> 4) [1,4,2,5]

推荐阅读