Haskell - 定义函数

4

我是一名编程和Haskell新手,我不太明白如何定义一个函数。假设我想要一个函数,它将返回列表[b]中位置为a的元素。对于特定的a[b],我可以在解释器中执行以下操作:

Prelude> [2, 3, 5, 6] !! 1
Prelude> 3

但是,如果我尝试创建一个函数,无论是在解释器中还是在文本编辑器中加载,都会遇到问题:

Prelude> let getElement a [b] = [b] !! a 
Prelude> getElement 1 [2, 3, 5, 6]
***Exception: <interactive>:17:5-27: Non-exhaustive pattern in function getElement

我手头没有编译器,但你可以在 [b] 上调用 heada 次。这样你就能学习一些递归了。 - mike
2
使用 b 代替 [b] - soulcheck
2
你需要 let getElement a b = b !! a。通过 [b],你指的是一个只包含一个元素 b 的列表。阅读 Haskell 教程会有所帮助。 - nickie
@mike,你需要使用tail而不是head - Rotsor
如果您使用ghci,我建议您在编辑器中进行更改,并将其保存在一个.hs文件中,然后使用:r <filename>.hs进行加载;您会收到错误消息,说明某些输入组合未被您提供的函数定义所覆盖。 - jev
1个回答

6
你的函数接受一个类型为Int的参数a,因为(!!)的第二个参数是Int类型,而[b]模式匹配了一个只有一个元素的列表。
看起来你试图告诉编译器第二个参数应该是一个列表。为了做到这一点,通常使用类型签名。
在文件中:
getElement :: Int -> [b] -> b
getElement a bs = bs !! a

这种类型的函数被认为是部分函数,因为您可以给它一个整数导致函数失败并抛出异常,比如负数或尝试访问大于列表长度的索引。这本《Real World Haskell》中的章节介绍了一些关于部分函数的信息。Haskell维基上的编程指南页面提供了一些建议

你可能需要看看safe包以及它们如何定义headMay以实现完整的而不是部分的功能。

编辑:b改为bs,根据Rein Henrichs的建议,因为它确实使得代码更易读,并且是一个相当常见的习惯用法。


8
稍微不那么令人困惑的叫法是 getElement a bs = bs !! a - Rein Henrichs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接