Haskell 哈斯克尔:99个问题#1:第一个解决方案不';不要在GHCi中运行

Haskell 哈斯克尔:99个问题#1:第一个解决方案不';不要在GHCi中运行,haskell,Haskell,第一个问题是编写一个函数来获取列表中的最后一个元素 解决方案部分提供的第一个解决方案是: myLast :: [a] -> a myLast [x] = x myLast (_:xs) = myLast xs 因此,在GHCi中,我做到了: Prelude> let myLast [a] = a Prelude> let myLast (_:xs) = myLast xs Prelude> myLast [1,2,3] 这给了我一个例外: *** Exception:

第一个问题是编写一个函数来获取列表中的最后一个元素

解决方案部分提供的第一个解决方案是:

myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
因此,在GHCi中,我做到了:

Prelude> let myLast [a] = a
Prelude> let myLast (_:xs) = myLast xs
Prelude> myLast [1,2,3]
这给了我一个例外:

*** Exception: <interactive>:12:5-29: Non-exhaustive patterns in function myLast
***异常::12:5-29:函数myLast中的非穷举模式

为什么不起作用?

它不起作用,因为您在GHCi中使用的
let
是错误的

let myLast [a] = a
这定义了一个只对一个元素的列表进行操作的函数
myLast

let myLast (_:xs) = mylast xs
这定义了一个新函数,
myLast
,它覆盖了上一行中的旧函数和无关函数。这个新函数为任何输入抛出异常(或无法终止)

您应该输入:

:{
let myLast [x] = x
    myLast (_:xs) = myLast xs
:}

或者,只需在文件中输入代码,而不是repl。我强烈建议您避免使用repl进行单行或交互式实验以外的任何操作。

当您在解释器中使用
let
时,这实际上是
IO
monad中的let,例如在do块中

do
  ...
  let x = ...
  ...
如果要从ghci内部定义递归函数,可以执行以下操作

Prelude> :edit file.hs
然后将在编辑器中打开文件
file.hs
(例如,在linux中,将选择通过环境变量
editor
指定的编辑器;通常,您可以通过
从ghci内部设置使用的编辑器:设置编辑器编辑器名称
;您可以通过将此设置添加到
~/.ghci
文件中,使此设置保持不变). 在此处输入函数定义。保存文件。然后将其加载到ghci中


现在
file.hs
中的定义将在范围内。

我认为您不能像那样在解释器中输入函数声明。我想这只是想起了你最近给出的定义。
Prelude> :load file.hs