我一直在为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' [] = [] → ──────────────────┘

07-24 09:26