为什么使用(> 100)部分应用?

时间:2015-05-14 15:42:25

标签: haskell

此代码说明了通过使用运算符部分来使用部分应用程序:

gt100 :: Integer -> Bool
gt100 x = x > 100


greaterThan100 :: [Integer] -> [Integer]
greaterThan100 xs = filter gt100 xs

greaterThan100_2 :: [Integer] -> [Integer]
greaterThan100_2 xs = filter (\x -> x > 100) xs


greaterThan100_3 :: [Integer] -> [Integer]
greaterThan100_3 xs = filter (>100) xs

操作员部分(> 100)部分地将操作员应用于一个操作员 它的两个论点。因此,在这种情况下,操作员是> 为什么这个部分应用程序是>正在应用运算符 到整个整数列表?

这与lambda表达式(\x -> x > 100)有什么不同呢? 显然不是部分申请?

取自http://www.seas.upenn.edu/~cis194/spring13/lectures/04-higher-order.html

更新:

感谢答案,这看起来更清楚。

现在我的理解是这样的:

*Main> :t (>)
(>) :: Ord a => a -> a -> Bool

根本不应用,因为它接受两个参数“a - > a”,但它们不会应用。

*Main> :t (>100)
(>100) :: (Ord a, Num a) => a -> Bool

部分应用作为“a - > Bool”类型的函数创建

*Main> :t (3>100)
(3>100) :: Bool

评估为键入Bool,它是运算符(>)的返回类型,如:t (>)所示

2 个答案:

答案 0 :(得分:5)

  

为什么这个部分应用程序是>运算符是否正在应用于整个整数列表?

它不是作为一个整体应用于整个列表,而是逐个应用于各个元素。当>部分应用于100时,它会创建一个新函数。

Prelude> :type (> 100)
(> 100) :: (Num a, Ord a) => a -> Bool

现在,该函数接受一个参数并返回Bool。此函数由filter函数应用于列表中的所有元素。

  

这与lambda表达式(\ x - > x> 100)有何不同,这显然不是部分应用?

>是一个需要两个操作数才能运行的函数。您已经传递了其中一个,100。要完全执行该函数,您还需要一个参数。因此,函数>部分应用了100

在第二种情况下,您正在创建一个只需要执行一个参数的新函数。传递该参数后,您的函数将被执行。因此,lambda函数不会部分应用。

答案 1 :(得分:3)

  

这个[(<) 100]与lambda表达式(\x -> (<) 100 x)有什么不同,这显然不是部分应用? [1]

我认为区分语义属性和句法属性很重要。你建议的两个术语在语义上相同 - 也就是说,你可以编写的Haskell函数在应用于(<) 100时减少到一个东西,并在应用于(\x -> (<) 100 x)时减少到另一个东西"(<) 100"

但是,部分应用程序是一个语法属性 - 也就是说,它不是行为的属性,而是特定实现的属性< / em>选择。 (与我对语义属性的定义类似,一个语法属性是关于你是否可以编写一个Haskell函数,当应用于字符串 "(\x -> (<) 100 x)"时,它会减少到一个并减少为当应用于字符串(<) 100时,这是不同的事情,这显然是可能的。)如果我必须定义它,我会这样定义:部分应用程序是带箭头类型的应用程序术语。 [2]你的两个术语都是打字好的并且有箭头类型。但是\x -> (<) 100 x是一个应用术语,而(100<)是一个lambda术语(在其体内有一个应用程序)。

对于像(>100)(<) 100这样的运算符部分,如何处理这些部分并不是很明显。一种选择是简单地判断所有操作员部分是部分应用程序(或者简单地判断当然没有操作员部分是部分应用程序)。另一种方法是将它们分别视为flip (>) 100\x -> (<) 100 x的简写,在这种情况下,我们仍然会将它们视为部分应用程序(因为它们是应用程序术语并具有箭头类型)。 [3]然而,第三种情况是将它们分别视为\x -> (>) x 100(<) 100的简写,在这种情况下,人们可能会声称它们不是部分申请。

但在我看来,这种区别并不太重要:通常,语义属性比仅仅是语法属性更有趣和有用。

[1]为避免混淆水域,我使用(>100)代替(!)。我们将很快讨论这一区别 [2]如果类型是多态的,有一些问题该怎么办。让我们暂时解决这个问题 [3]这不同于简单地判定所有操作员部分都是部分应用程序;考虑一些单参数运算符(100!)及其(!) 100部分,我们将其视为Invariant Violation: Expected a component class, got [object Object]. 的简写。这是一个应用术语,但其类型中没有箭头。