在haskell中查找列表的最后一个元素

时间:2017-12-18 21:32:21

标签: list haskell functional-programming

我编写了以下代码来查找haskell中列表的最后一个元素:

myLast (x:xs) = do
    ret <- if xs == [] then x else (myLast xs)
    return ret

我们的想法是遍历列表,直到我们处于一个以空列表作为下一个元素的元素。当我们找到它时,我们将ret设置为该元素。 这对我来说很有意义,但是当我在交互式shell中运行代码时,我收到以下错误:

<interactive>:1:1: error:
    • No instance for (Num (m0 b0)) arising from a use of ‘it’
    • In a stmt of an interactive GHCi command: print it

编辑1

我使用do的原因是因为我看到在某处使用该模式也遍历列表,所以我想我可以在这里做同样的事情。我现在正在避免使用图书馆来熟悉这门语言。 我写了避免do关键字的函数,现在它可以工作:

myLast(x:xs) = if xs == [] then x else (myLast xs)

现在只是空列表案例的问题。如何在haskell中解决这个问题?

2 个答案:

答案 0 :(得分:2)

让我们从你的功能签名开始

myLast :: [a] -> a

现在,对于空列表输入,可以预期什么作为输出?如何组成任意类型a的实例?

或者,您可以将丢失的最后一个元素的处理推迟到函数的调用者。

myLast :: [a] -> Maybe a

答案 1 :(得分:1)

你想要

myLast (x:xs) =

等于

                if xs == [] then x else (myLast xs)

很好,xs == [],所以让我们把它放回去:

myLast (x:[]) =                  x 

else部分怎么样?好吧,让我们为此添加另一个等式,

myLast (_:xs) =                          myLast xs

我们是金色的。

如果我们用空列表[]调用它会怎么样?没有定义案例匹配,我们将得到某种运行时错误。好吧,同样的事情也发生在内置函数last上,所以我们在这里没有比Haskell本身更好和没有更差

我提到的匹配是什么,你问?那就是如何调用Haskell函数。每个函数定义都可以有多个子句,从函数的名称开始,并包含每个预期参数的模式

在等式的左边,

  • (x:[])是一个匹配任何单例列表的模式。它也可以写成[x]x将引用列表中唯一的元素,如果在等式的右侧使用。

  • []是一种模式,匹配任何空列表。

  • (x:xs)是一种模式,匹配任何非空列表。如果在等式的右侧使用,x将引用列表的 head (即第一个)元素; xs将引用列表中元素的 rest (也是列表 - 也称为 tail )。

但等等,你问。单个列表 匹配空列表[x]

为什么是,他们两个确实匹配; (_:xs)xs 互斥。

但是没关系,因为在Haskell中,如果第一个子句匹配,那就是 - 是执行的子句,没有其他尝试进行任何其他模式匹配和子句选择。

那将是Prolog,而那是另一种语言。