为什么在Prelude中有两个init函数定义?

all*_*ass 7 haskell

我在Prelude中发现了函数init的两个定义:

init [x] = []
init (x:xs) = x : init xs
init [] = errorEmptyList "init"

init [] = errorEmptyList "init"
init (x:xs) = init' x xs
  where init' _ [] = []
        init' y (z:zs) = y : init' z zs
Run Code Online (Sandbox Code Playgroud)

第二个定义的原因是什么?

Bar*_*icz 12

您没有逐字引用它。实际上是:

-- | Return all the elements of a list except the last one.
-- The list must be non-empty.
init                    :: [a] -> [a]
#if defined(USE_REPORT_PRELUDE)
init [x]                =  []
init (x:xs)             =  x : init xs
init []                 =  errorEmptyList "init"
#else
-- eliminate repeated cases
init []                 =  errorEmptyList "init"
init (x:xs)             =  init' x xs
  where init' _ []     = []
        init' y (z:zs) = y : init' z zs
#endif
Run Code Online (Sandbox Code Playgroud)

USE_REPORT_PRELUDE意味着这段代码符合Haskell Report,而另一段则可能是更有效的实现。请查看此主题,以获取有关的类似讨论reverse

  • @allmass不是。检查`[]`是* first *子句的模式匹配的一部分,而不是第三个子句的匹配:`[x]`实际上是((:) x []`(正如chi指出的),所以我们不仅要检查它是`:`,而且它的右分支中还有`[]`。这是对一种模式匹配的两次检查。 (3认同)