gpt4 book ai didi

haskell - Haskell函数参数的顺序有没有意义?

转载 作者:行者123 更新时间:2023-12-04 04:48:52 27 4
gpt4 key购买 nike

我一直在学习 Haskell,我注意到许多内置函数接受参数的顺序与我的预期相反。例如:

replicate :: Int -> a -> [a]

如果我想复制 7 两次,我会写 replicate 2 7 .但是当用英语大声朗读时,函数调用感觉就像是在说“复制 2、7 次”。如果我自己编写函数,我会交换第一个和第二个参数,以便 replicate 7 2将阅读“复制 7、2 次”。

在我浏览 99 Haskell Problems 时出现了一些其他示例.我不得不写一个函数:
dropEvery :: [a] -> Int -> [a]`

它接受一个列表作为它的第一个参数和一个 Int作为它的第二个。直观地说,我会将标题写为 dropEvery :: Int -> [a] -> [a]这样 dropEvery 3 [1..100]将读作:“删除列表中的每三个元素 [1..100] 。但在问题的示例中,它看起来像: dropEvery [1..100] 3

我还看到了其他我现在找不到的功能。由于实际原因,以这种方式编写函数是否很常见,或者这一切都只是在我的脑海中?

最佳答案

以这种方式编写函数的原因之一是因为它们的柯里化(Currying)形式非常有用。

例如,考虑函数 mapfilter :

map :: (a -> b) -> [a] -> [b]
filter :: (a -> Bool) -> [a] -> [a]

如果我想将偶数保留在一个列表中,然后将它们除以 2,我可以这样写:
myfunc :: [Int] -> [Int]
myfunc as = map (`div` 2) (filter even as)

也可以这样写:
myfunc = map (`div` 2) . filter even
\___ 2 ____/ \___ 1 ___/

将其设想为从右到左的管道:
  • 首先我们保留偶数(步骤 1)
  • 然后我们将每个数字除以 2(步骤 2)
  • .操作符作为将管道段连接在一起的一种方式 - 很像 |运算符在 Unix shell 中工作。

    这一切都是可能的,因为 map 的列表参数和 filter是这些函数的最后一个参数。

    如果你写你的 dropEvery用这个签名:
    dropEvery :: Int -> [a] -> [a]

    然后我们可以将它包含在这些管道之一中,例如:
    myfunc2 = dropEvery 3 . map (`div` 2) . filter even

    关于haskell - Haskell函数参数的顺序有没有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31736467/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com