实现最后一个功能

use*_*056 8 haskell

我正在努力教自己Haskell.我试图做的一件事是编写一个替代函数,通过递归列表返回列表的最后一个元素,直到尾部为空集然后返回头部.我有...

mylast [] = []
mylast (x:[]) = x
mylast (x:xs) = mylast xs
Run Code Online (Sandbox Code Playgroud)

...但是当我尝试任何非空列表时出现错误:(有关我做错了什么的建议吗?TIA.

rtp*_*son 31

问题 - 就像你学习Haskell时的许多其他问题一样 - 是打字的问题.在GHCi中键入以下内容

:t mylast
Run Code Online (Sandbox Code Playgroud)

你会看到类型签名是

mylast :: [[a]] -> [a]
Run Code Online (Sandbox Code Playgroud)

需要列表列表并返回列表.因此,如果您输入字符串列表["bob","fence","house"],该函数将在您编写时起作用.

问题是你的基本情况:mylast [] = [],告诉编译器你想要返回一个列表.您想要返回一个元素,而不是一个列表.但是Haskell中没有空元素(非常多的是设计),所以你需要使用Maybe monad.

mylast :: [a] -> Maybe a
mylast [] = Nothing
mylast (x:[]) = Just x
mylast (x:xs) = mylast xs
Run Code Online (Sandbox Code Playgroud)

Monads是一个有点抽象的话题,但是当你开始时你需要Maybe monad.所有你需要知道的是它是一个类型声明,告诉编译器期望两种可能性:"Nothing"或"Just x".返回的代码然后可以使用x并运行它,但是如果你不使用"Just",编译器会抱怨.

另一种方法是在遇到空列表时抛出错误,如下所示:

mynextlast [] = error "no empty lists allowed"
mynextlast (x:[])  = x
mynextlast (x:xs) = mynextlast xs
Run Code Online (Sandbox Code Playgroud)

但我怀疑可能是要走的路.

  • 从中可以得出一个教训,即指定您定义的东西类型很有用.它将使编译捕获这样的错误.. (6认同)

EFr*_*aim 8

试试吧mylast [] = error "Empty list!".否则Haskell无法推断出你的函数类型.


Cra*_*ntz 6

EFraim的解决方案应该有效(投票).但我认为这更像是"类似Haskell":

mylast [] = Nothing
mylast (x:[]) = Just x
mylast (x:xs) = mylast xs
Run Code Online (Sandbox Code Playgroud)

免责声明:我实际上没有试过这个.我可能犯了语法错误.

  • 中间案例与[x]相同,对吧?IOW,通过将x与空列表"(x:[])"连接而创建的一个元素列表与仅包含x"[x]"的列表相同.不过,我不知道哪一个更惯用. (2认同)