为什么Haskell中的这个“@”用法不能包含整个列表?

我正在解决 99 个 Haskell 问题并尝试使用这段代码来解决第二个问题,这需要返回数组的倒数第二个元素:

myPen :: [a] -> a
myPen [] = error "Empty lists have no penultimate element."
myPen list@(_:xs)
  | length list == 1  = error "Lists size 1 have no penultimate element."
  | length xs == 2    = head xs
  | otherwise         = myPen xs

这段代码可以编译,但是当给出输入时

myPen [1,2]

它产生错误

*** Exception: Lists size 1 have no penultimate element.
CallStack (from HasCallStack):
  error, called at prob1_10.hs:16:25 in main:Main

据我所知,@在这种情况下应该允许引用整个列表,但它似乎只引用xs了列表的或尾部。

这似乎支持了它应该同时包含x和的论点xs

我的问题有两个:

1.) 这是为什么?2.) 引用整个列表的正确方法是什么?

回答

在这种情况下发生的情况实际上是length list == 2, but length xs == 1,因此第一个或第二个守卫都不会匹配。该otherwise防护件将采取并调用该函数递归上xs,其具有长度为1,以便在第一防护件将采取以及将被打印的错误信息。你可以通过写来修复它:

myPen :: [a] -> a
myPen [] = error "Empty lists have no penultimate element."
myPen list@(_:xs)
  | length list == 1  = error "Lists size 1 have no penultimate element."
  | length list == 2  = head list
  | otherwise         = myPen xs

但是在 Haskell 中,使用模式匹配而不是length函数来执行此操作通常更常见,如下所示:

myPen :: [a] -> a
myPen []     = error "Empty lists have no penultimate element."
myPen [_]    = error "Lists size 1 have no penultimate element."
myPen [x,_]  = x
myPen (_:xs) = myPen xs


以上是为什么Haskell中的这个“@”用法不能包含整个列表?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>