Map函数将非函数作为第一个参数

时间:2015-04-17 06:13:32

标签: haskell

-- file: ch19/divby1.hs
divBy :: Integral a => a -> [a] -> [a]
divBy numerator = map (numerator `div`)

这是O' reilly - Haskell书中的代码摘录。

示例运行为,

ghci> divBy 50 [1,2,5,8,10]
[50,25,10,6,5]

令我困惑的是

  1. 为什么表达式中LHS divBynumerator有两个变量:

    divBy numerator = map (numerator `div`)
    
  2. 最后分配的变量divBynumerator是什么值?

    1. map函数类型是 map :: (a -> b) -> [a] -> [b]。 在上面的表达式中,参数numerator不是函数类型,而且 div不是数组类型。但是代码正在运行!!
    2. 我在这里缺少什么?

2 个答案:

答案 0 :(得分:4)

关于eta转换和签名的

首先我想你错过了一些`:在numerator `div`中(是的,我认为这样做了 - 你必须输入`` numerator `div` ``来工作!)

此:

divBy :: Integral a => a -> [a] -> [a]
divBy numerator = map (numerator `div`)

是另一种写作方式

divBy :: Integral a => a -> [a] -> [a]
divBy = \ numerator -> map (numerator `div`)

可以扩展到

divBy :: Integral a => a -> [a] -> [a]
divBy = \ numerator ns -> map (numerator `div`) ns

如果你愿意,可以将参数放回左边:

divBy :: Integral a => a -> [a] -> [a]
divBy numerator ns -> map (numerator `div`) ns

这里可能更清楚的是numerator是第一个参数(类型为a)而ns是第二个([a]类型)而divBy 1}}当然是函数的名称。

这是有效的,因为有一些名为eta conversion的内容基本上表示您可以将\x -> f x简化为f - 但有时候要注意run into trouble这个但是它&# 39;经常用于编写point-free-style Haskell代码。

你的问题

  

令我困惑的是

     

为什么表达式中的LHS divBy和numerator有两个变量:

divBy numerator = map (numerator `div`)

答案:那些不是变量 - 第一个是您在此行中声明的函数的名称,第二个是它的名称' s第一个论点。

你可能想知道第二个去哪了(见上文) - 简短的回答是:divBy实际上是一个函数,它接受a并返回另一个函数[a] -> [a]所以那里只要你返回一个函数(并且你做),你实际上只有一个参数。

  

什么值,最后分配变量divBy和numerator?

回答:正如我所说divBy是你的函数的名称 - numerator将获得第一个参数,所以

 λ> divBy 5 [1..10]
 [5,2,1,1,1,0,0,0,0,0]

numerator5

  

map函数类型为map :: (a -> b) -> [a] -> [b]在上面的表达式中,参数numerator不是函数类型,div不是数组类型。但是代码正在运行!!

     

我在这里缺少什么?

基本上你错过了括号 - (numerator `div`)是一个所谓的section - 它实际上是函数\n -> numerator `div` n - 认为它有一个 infix `div`的第二个参数:(免责声明:伪代码)(numerator `div` _)

所以(numerator `div`)实际上是一个函数Integral a => a -> a,所以它适合map的第一个参数。

现在第二个在哪里?再说一遍,就像上面一样:map (numerator `div`)是一个函数Integral a => [a] -> [a],这就是你的声明divBy numerator右边缺少的东西。

我希望你能在这个答案的第一部分找到我给你的东西。

如果您有疑问,请发表评论 - 我会尝试在需要时添加解释。

答案 1 :(得分:1)

我会像这样阅读这段代码:

divBy的类型表示它需要两个参数[1],a[a],但其声明的LHS只显示一个参数,即{{1 }}。所以,让我自己添加第二个参数,以完成图片:

numerator

请注意,我使用名称divBy numerator xs = map (numerator `div`) xs(读作x-es,因为"多个x"),因为第二个参数是一个列表。我可以使用,比如说xs,但是使用x是一个视觉提示,即事物是一个列表,它可以帮助我避免混淆。

现在情况看起来更清楚了:

  1. xs与说divBy numerator xs完全一样:无论我在哪里看到前一个表达式,我都可以用后一个表达式替换它。
  2. map (numerator `div`) xs看起来相当不错:map (numerator `div`) xs的第二个参数map绝对是一个列表,应该是它。 xs的第一个参数map需要是(numerator `div`)类型的函数,其中a -> aa的实例类型。也就是说,Integral必须成立。所以现在我只需要关注为什么会出现这种情况。
  3. 我试图找出(numerator `div`) :: Integral a => a -> a为什么类型(numerator `div`)。其他答案已经解释了为什么会这样,我很高兴!
  4. [1]要迂腐,Integral a => a -> a只接受一个论点等,但我现在正在教育学。