我一直在为Haskell使用一些资源:向您学习Haskell和Wikibook。但是,我正在努力寻找一个可以帮助我更多地了解递归的解释。我已经附上了我部分理解的“学习Haskell”书中的示例代码。
maximum' :: (Ord a) => [a] -> a
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
我理解以上所有代码,直到最后一行'maxTail = maximum'xs'。我不明白的是,如何对代码进行评估以从调用“maximum”返回最大值。或如何知道“最大值”是列表中的最高元素。
另一个例子:
reverse' :: [a] -> [a]
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
理解所有内容,直到在列表的尾部调用“reverse”为止。换句话说,如何知道“反转”意味着反转尾元素。
我很感谢您的解释,如果很简单,我深表歉意,我是这种语言的新手。
最佳答案
逐行浏览,希望您能更好地理解它:
1| maximum' :: (Ord a) => [a] -> a
2| maximum' [] = error "maximum of empty list"
3| maximum' [x] = x
4| maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
在第1行中,您说获得了a的列表并返回该类型的一个元素。另外,该列表中的元素必须是可排序的,因此您可以将它们排序。
在第2行中,您有一个边缘情况,您说如果得到一个空列表作为输入,则该空列表中不会有“最高值”,因此您将在函数结尾处出现错误。
在第3行中,您有另一种极端情况,即您说如果获得的列表包含1个元素,则该元素必须是最高元素,因此您将其返回。
在第4行中:使用模式匹配来匹配第一个元素(
x
)和列表的其余部分(xs
)。然后,您检查x
是否大于maxTail
,其中maxTail
和函数maximum'
的函数结果与列表xs
的其余部分一起使用。如果该
x
大于maxTail
,则返回x
,否则maxTail
大于x
,然后返回maxTail
。我认为带有一些数字的示例在这里也应有所帮助:
输入:
[2, 5, 4, 13]
call :
maximum' [2, 5, 4, 13]
怎么了:
maximum' (x : xs)
↓ ↓
maximum' (2:[5, 4, 13])
│
↓ result 13
x > maxTail = x ↑
2 > maximum' [5, 4, 13] = x //2 > 13 = 13 ← ────┐
│ │
└ maximum' (x : xs) │
↓ ↓ │
maximum' (5:[4, 13]) │
│ │
↓ ↑
x > maxTail = x │
5 > maximum' [4, 13] = x //5 > 13 = 13 ← ─────┐
│ │
└ maximum' (x: xs) │
↓ ↓ │
maximum' (4:[13]) │
│ │
↓ ↑
x > maxTail = x │
4 > maximum' [13] = x //4 > 13 = 13 ┐
│ │
└ maximum' [x] = x ↑
maximum' [13] = 13 → ───────────┘
在您的第二个示例中,它几乎是相同的:
1| reverse' :: [a] -> [a]
2| reverse' [] = []
3| reverse' (x:xs) = reverse' xs ++ [x]
在第1行中,您说获得了a的列表并返回了a的列表。
在第2行中,您有一个边缘案例,您说如果得到一个空列表,则反向列表也只是空的。
在第3行中,您再次使用模式匹配来匹配列表的第一个元素(
x
)和列表的尾部(xs
)。现在,您只需要使用
++
将两个列表附加在一起,这是列表的第一个元素,其尾部相反。再一次,我希望通过一个例子可以使它更加清晰:
输入:
[1, 2, 3]
call :
reverse' [1, 2, 3]
怎么了:
reverse' (x : xs)
↓ ↓
reverse' (1:[2, 3])
│ result [3, 2, 1]
↓ ↑
(reverse' [2, 3]) ++ [1] //[3, 2] ++ [1] = [3, 2, 1] ← ────┐
│ │
└ reverse' (x: xs) │
↓ ↓ │
reverse' (2:[3]) │
│ ↑
↓ │
(reverse' [3]) ++ [2] //[3] ++ [2] = [3, 2] ← ───┐ → ┘
│ │
└ reverse' (x:xs) │
↓ ↓ │
reverse' (3:[]) │
│ ↑
↓ │
(reverse' []) ++ [3] //[] ++ [3] = [3] ┐ → ┘
│ ↑
└ reverse' [] = [] → ──────────────────┘