Haskell中的参数和列表

ghhaqwfi  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(153)

我是Haskell的超级新手。来自其他语言,如Java或C,我在理解Haskell中的函数如何使用参数方面有一些问题。我理解多态性的概念,Haskell如何使用类型,以及所有东西看起来像一棵树,但我很难将这些概念应用到语法中。
比如说,我想编写一个函数,它接受一个字符串列表,只在其中添加“1”和“2”。

addOneTwo :: [String] -> [String]
addOneTwo [] = "1" : "2" : [x]

我知道这个问题可能在其他地方得到了回答,但我还没有看到一个答案,以某种方式解释它,使我作为一个完全的新手可以理解。

koaltpgm

koaltpgm1#

addOneTwo :: [String] -> [String]
addOneTwo [] = "1" : "2" : [x]

这表示:

  • addOneTwo是接受[String]并返回[String]的函数
  • 当在空列表(即addOneTwo [])上调用addOneTwo时,它将计算为一个列表,其中:
  • 头部为"1"
  • 尾部是一个列表,其中:
  • 头部为"2"
  • tail是一个元素的列表,x(或者,换句话说,它的头是x,它的尾是[]

由于您没有在此代码中定义名为x的变量,因此这是一个作用域错误。修复此错误的一种方法如下:

  • 删除模式[],并将其替换为模式x,即只是一个参数名。
  • 由于此参数是一个列表,因此直接将其用作cons运算符(:)的第二个操作数,即… : x而不是 * … : [x]
addOneTwo :: [String] -> [String]
addOneTwo x = "1" : "2" : x

传统上,列表通常以s为后缀命名,如xsstrings,因此如果愿意,您也可以重命名x
为了更深入地理解你的原始代码,也许回顾一下它是如何脱糖的会很有启发性:

addOneTwo =
  \ xs -> case xs of {
    [] -> "1" : ("2" : (x : []));
    _ -> error "Non-exhaustive patterns in function addOneTwo"
  }

因为addOneTwo是一个函数,所以可以用function value 来定义它,也就是lambda表达式,我给这个函数的参数命名为xs,当你写定义addOneTwo [] = …的时候,patternaddOneTwo []表示您正在定义 expressionaddOneTwo []的计算结果。“等号”实际上表示“等于”!
这等效于使用case表达式显式获取一个参数并对其进行模式匹配。注意,我包含了一个error情况,当您没有覆盖所有可能的输入时,它会隐式生成-在本例中,当addOneTwo应用于非空列表时,如果您启用-Wincomplete-patterns,GHC可以警告您此类未覆盖的情况; -Wall暗示了这一点,它会生成各种其他有用的警告。
然而,更正后的定义将去糖为:

addOneTwo =
  \ x ->
    "1" : ("2" : x)

由于所有输入都将通过模式x进行匹配,因此根本不需要error替代项或任何case表达式。
我想编写一个函数,它接受一个字符串列表,只在其中添加“1”和“2”。
好吧,就这样!但是记住:这并不是将元素添加到 same 列表中,而是创建一个与旧列表共享某个后缀的列表。这是Haskell中表示数据结构增量更新的正常方式:函数f :: T -> T接受表示一个状态的值,并返回表示修改后的状态的值,并且我们依赖于垃圾收集器来回收不再使用的旧状态的部分。

相关问题