Haskell/解决方案/列表和元组
外观
练习 |
---|
let myCons list thing = |
- 这将无法正常工作。[True, False]是一个布尔值列表,3是一个整数。
let cons8 list = 8:list
、let cons8 = (:) 8
和let cons8 list = (:) 8 list
都是有效的函数。cons8 []
返回[8]
cons8 [1,2,3]
返回[8,1,2,3]
cons8 [True,False]
会导致类型错误。这与练习 1 中的错误相同。let foo = cons8 [1,2,3]
不会输出任何消息,但 foo 为[8,1,2,3]
。试试看!cons8 foo
(假设你完成了 2.4)返回[8,8,1,2,3]
- 正如我们所知,
let cons8 list = list:8
无法正常工作,因为 8 不是列表,但let cons8 list = list ++ [8]
会正常工作,因为 (++) 会连接两个列表 let myCons list thing = thing : list
、let myCons list thing = (:) thing list
都是有效的函数。
练习 |
---|
|
- 1 和 2 不是有效的 Haskell 代码,3 是有效的
1:2:3:[]:[]
。1
、2
和3
是整数,而[]
是一个列表。1:(2:3:[]):4:[]
。同样,1
和4
是整数,而2:3:[]
是一个整数列表。(1:2:3:[]):[]:[]
。这是有效的 Haskell 代码,因为1:2:3:[]
是一个整数列表,而[]
是一个空列表(任何类型)。
- 前四个是有效的 Haskell 代码。第五个不是。
[[],[1,2,3],[4,5,6]]
。[1,2,3]
和[4,5,6]
都是整数列表。整个列表是一个整数列表的列表。我们可以将一个空列表(任何类型)连接到它的前面。[[]]
。不是空列表!。这是一个包含一个空列表的列表。该列表本身不是空的,因为它有一个元素![[],[]]
。这是一个包含两个空列表的列表。[[1],[]]
。这与前一个列表相同,只是第一个元素为[1]
,而不是[]
。由于该列表是一个列表的列表,它现在已成为一个整数列表的列表。[["hi"], [1]]
。["hi"] 是一个字符列表,而 [1] 是一个整数列表。
- 是的,这是可能的。例如:
[[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]]
。为什么?你可以创建一个任何类型的列表!如果你已经有一个某种类型的列表,那么你可以创建一个该类型列表的列表。示例列表将写成:((1:[]):(2:[]):(3:[]):[]):((4:[]):(5:[]):(6:[]):[]):((7:[]):(8:[]):(9:[]):[]):[]
- 列表
[[1,2],3,[4,5]]
无效,因为它等效于(1:2:[]):3:(4:5:[]):[]
,我们尝试连接不同类型的元素(即列表和数字)。Haskell 中的列表必须是类型同质的。有效的列表将是[[1,2],[3],[4,5]]
,等效于(1:2:[]):(3:[]):(4:5:[]):[]
。
练习 |
---|
|
(4,"hello",True)
- 它们都是有效的!元组不受类型的限制。
- 一个包含两个整数的元组。
- 一个包含一个整数和一个字符串的元组。
- 一个包含一个布尔值和两个字符串的元组。
- 空元组
()
被称为“单位”
-
- 也许 Haskell 的创建者希望限制元组的功能,以避免过度使用它们。使用可连接的元组而不是列表和元组来提供函数参数的习惯,可能使函数变得更加复杂,因此更难阅读、编写和维护。
- 与列表不同,我们将获得一个具有不同类型的元组,因为元组的大小将更大。
练习 |
---|
|
-
- 无效。
(2,3)
是一个元组,而连接(:)
仅适用于列表。 - 无效。
(2,3)
是一个元组,而连接(:)
仅适用于列表。 - 有效。你将得到一个包含一个整数和一个整数的元组的列表:
[(2,4)]
- 无效。列表的所有元素必须是相同类型。
(2,4)
和(5,5)
是包含一个整数和一个整数的元组,但('a','b')
是包含一个字符和一个字符的元组。 - 有效。这是一个包含一个整数列表和一个整数列表的元组。
- 无效。
练习 |
---|
|
snd (fst (("Hello", 4), True))
返回4
。- 是的,我们可以!元组和列表之间的区别在于,列表的所有元素必须是相同类型(整数、布尔值等),但你可以向列表添加元素。元组的元素可以是任何你想要的类型,例如
(4, 'a')
中的整数和字符的元组,但你不能更改其大小。 headAndTail list = (head list, tail list)
- 此实现的缺点包括定义的笨拙性、缺乏通用性(如果我们想获取第四个、第六个或第十九个元素呢?)、以及它会在传入一个元素少于五个的列表时导致程序崩溃的事实。
fifthElement list = head (tail (tail (tail (tail list))))
练习 |
---|
为以下函数提供类型签名
|
headAndTail :: [a] -> (a, [a])
fifthElement :: [a] -> a
h x y z :: Int -> a -> b -> Char -- y and z are not actually used, so their types could be anything