我是Haskell的超级新手。来自其他语言,如Java或C,我在理解Haskell中的函数如何使用参数方面有一些问题。我理解多态性的概念,Haskell如何使用类型,以及所有东西看起来像一棵树,但我很难将这些概念应用到语法中。
比如说,我想编写一个函数,它接受一个字符串列表,只在其中添加“1”和“2”。
addOneTwo :: [String] -> [String]
addOneTwo [] = "1" : "2" : [x]
我知道这个问题可能在其他地方得到了回答,但我还没有看到一个答案,以某种方式解释它,使我作为一个完全的新手可以理解。
1条答案
按热度按时间koaltpgm1#
这表示:
addOneTwo
是接受[String]
并返回[String]
的函数addOneTwo []
)上调用addOneTwo
时,它将计算为一个列表,其中:"1"
"2"
x
(或者,换句话说,它的头是x
,它的尾是[]
)由于您没有在此代码中定义名为
x
的变量,因此这是一个作用域错误。修复此错误的一种方法如下:[]
,并将其替换为模式x
,即只是一个参数名。(:)
的第二个操作数,即… : x
而不是 *… : [x]
传统上,列表通常以
s
为后缀命名,如xs
或strings
,因此如果愿意,您也可以重命名x
。为了更深入地理解你的原始代码,也许回顾一下它是如何脱糖的会很有启发性:
因为
addOneTwo
是一个函数,所以可以用function value 来定义它,也就是lambda表达式,我给这个函数的参数命名为xs
,当你写定义addOneTwo [] = …
的时候,patternaddOneTwo []
表示您正在定义 expressionaddOneTwo []
的计算结果。“等号”实际上表示“等于”!这等效于使用
case
表达式显式获取一个参数并对其进行模式匹配。注意,我包含了一个error
情况,当您没有覆盖所有可能的输入时,它会隐式生成-在本例中,当addOneTwo
应用于非空列表时,如果您启用-Wincomplete-patterns
,GHC可以警告您此类未覆盖的情况;-Wall
暗示了这一点,它会生成各种其他有用的警告。然而,更正后的定义将去糖为:
由于所有输入都将通过模式
x
进行匹配,因此根本不需要error
替代项或任何case
表达式。我想编写一个函数,它接受一个字符串列表,只在其中添加“1”和“2”。
好吧,就这样!但是记住:这并不是将元素添加到 same 列表中,而是创建一个与旧列表共享某个后缀的列表。这是Haskell中表示数据结构增量更新的正常方式:函数
f :: T -> T
接受表示一个状态的值,并返回表示修改后的状态的值,并且我们依赖于垃圾收集器来回收不再使用的旧状态的部分。