【问题标题】:Why is the use of (>100) partial application?为什么使用(> 100)部分应用程序?
【发布时间】:2015-05-15 00:14:32
【问题描述】:

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

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 (>) 所示

【问题讨论】:

  • 实际上并没有什么不同,因为它们都具有相同的类型和行为。

标签: haskell


【解决方案1】:

为什么这个部分应用作为 > 操作符被应用到整个 Integer 列表?

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

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

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


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

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

在第二种情况下,您正在创建一个只需要一个参数即可执行的新函数。一旦你传递了那个参数,你的函数就会被执行。因此,lambda 函数并未部分应用。

【讨论】:

    【解决方案2】:

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

    我认为区分语义属性和句法属性很重要。您建议的两个术语在语义上是相同的——也就是说,没有可以编写的 Haskell 函数在应用于 (<) 100 时简化为一件事,而在应用于 @987654324 时简化为另一件事@。

    然而,部分应用是一个句法属性——也就是说,它不是一个术语的行为属性,而是特定实现 选择。 (与我对语义属性的定义类似,句法属性是关于您是否可以编写一个 Haskell 函数,当应用于 字符串 "(<) 100" 时,该函数可以简化为一件事,并简化为另一件事当应用于字符串"(\x -> (<) 100 x)"时,这是非常可能的。)如果我必须定义它,我会这样定义:部分应用是一个带有箭头类型的应用术语。 [2] 你的两个术语都是很好的类型并且有箭头类型。但是(<) 100 是一个应用程序术语,而\x -> (<) 100 x 是一个 lambda 术语(它的主体中有一个应用程序)。

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

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

    [1] 为避免混淆,我使用了(<) 100 而不是(>100)。我们将很快讨论这个区别。
    [2] 如果类型是多态的,则存在一些问题。让我们暂时讨论这个问题。
    [3] 这不同于简单地规定所有操作员部分都是部分应用程序;考虑一些单参数运算符(!) 及其部分(100!),然后我们将其视为(!) 100 的简写。这是一个应用术语,但其类型中没有箭头。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-04
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多