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

Haskell Map函数将非函数作为第一个参数,haskell,Haskell,这是从O'reilly-Haskell的书中摘录的代码 样本运行方式: -- file: ch19/divby1.hs divBy :: Integral a => a -> [a] -> [a] divBy numerator = map (numerator `div`) 让我困惑的是 为什么表达式中的LHSdivBy和momerator上有两个变量: ghci> divBy 50 [1,2,5,8,10] [50,25,10,6,5] 变量除以和分子在末尾分配

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

样本运行方式:

-- file: ch19/divby1.hs
divBy :: Integral a => a -> [a] -> [a]
divBy numerator = map (numerator `div`)
让我困惑的是

  • 为什么表达式中的LHS
    divBy
    momerator
    上有两个变量:

    ghci> divBy 50 [1,2,5,8,10]
    [50,25,10,6,5]
    
  • 变量
    除以
    分子
    在末尾分配了哪些值

  • map
    功能类型为
    map::(a->b)->[a]->[b]
    。 在上面的表达式中,参数
    分子
    不是函数类型,并且
    div
    不是数组类型。但是代码正在运行 我在这里遗漏了什么?

    关于eta转换和签名 首先,我想你错过了一些
    `
    :在
    分子div`
    中(是的,我想你吃了它们-你必须输入这个作为
    ``分子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
    
    这里可能更清楚的是,
    分子
    是第一个参数(类型为
    a
    ),而
    ns
    是第二个参数(类型为
    [a]
    ),而
    divBy
    当然是函数的名称

    这是因为有一个名为的东西,基本上说你可以把
    \x->fx
    缩短为
    f
    ——但有时要注意,它通常用于编写Haskell代码

    你的问题 让我困惑的是

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

    ghci> divBy 50 [1,2,5,8,10]
    [50,25,10,6,5]
    
    答案:这些不是变量-第一个是您在此行中声明的函数的名称,第二个是它的第一个参数的名称

    您可能想知道第二个函数去了哪里(见上文)-简短的回答是:
    divBy
    实际上是一个函数,它接受一个
    a
    并返回另一个函数
    [a]->[a]
    ,因此,只要返回一个函数,实际上您只需要给出一个参数(确实如此)

    最后分配了哪些值、变量除数和分子

    答案:正如我所说的,
    divBy
    是函数的名称-
    分子
    将得到第一个参数

    divBy numerator = map (numerator `div`)
    
    分子
    5

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

    我错过了什么

    基本上你缺少了括号-
    (分子'div`)
    是一个所谓的函数-
    \n->分子'div`n
    -把它想象成中缀的第二个参数有一个洞:(免责声明:伪代码)
    (分子'div`

    所以
    (分子'div')
    实际上是一个函数
    积分a=>a->a
    ,因此它适合
    映射的第一个参数

    第二个在哪里?同样,这与上面的故事是一样的:
    map(分子'div')
    是一个函数
    积分a=>[a]->[a]
    ,这就是您声明的右侧所缺少的
    除以分子

    我希望你能用我在第一部分给你的答案来理解


    如果您有问题,请留下评论-我将尝试在需要的地方添加解释。

    我会像这样阅读此代码:

    divBy
    的类型表示它需要两个参数[1],一个
    a
    和一个
    [a]
    ,但其声明的LHS只显示一个参数,即
    分子
    。让我自己加上第二个论点,来完成这幅图:

    divBy分子xs=map(分子'div`)xs

    注意,我使用了名称
    xs
    (在“多个x”中读作x-es),因为第二个参数是一个列表。我本可以使用,比如说
    x
    ,但是使用
    xs
    是一个直观的提醒,它是一个列表,在以后避免混淆方面有很大帮助

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

  • divBy分子xs
    与说
    map(分子'div`)xs
    完全相同:无论我在哪里看到前一个表达式,我都可以用后一个表达式替换它
  • map(分子'div')xs在我看来相当不错:
    map
    的第二个参数是
    xs
    ,它应该是一个列表。
    map
    (分子'div')
    的第一个参数需要是
    a->a
    类型的函数,其中
    a
    整数的一个实例。也就是说,
    (分子'div')::积分a=>a->a
    必须保持不变。所以现在我只需要关心为什么会这样
  • 我试图弄明白为什么
    (分子'div')
    的类型是
    积分a=>a->a
    。其他答案解释了为什么会这样,我很高兴
    [1] 为了学究气,
    divBy
    只接受一个论点等,但我现在是一个教育学者

    我想,你错过了地图中div周围的符号(分子div)是的,这是stack.overflow效应。。让我纠正一下。。。
    divBy numerator = map (numerator `div`)
    
     λ> divBy 5 [1..10]
     [5,2,1,1,1,0,0,0,0,0]