Haskell GHCi中的缩进错误,实现过滤器

Haskell GHCi中的缩进错误,实现过滤器,haskell,Haskell,我错过了什么模式 Prelude> let filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs Prelude> let filter' _ [] = [] Prelude> filter' odd [1..10] *** Exception: <interactive>:1:5-21: Non-exhaustive patterns in function filter' 在g

我错过了什么模式

Prelude> let filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs
Prelude> let filter' _ [] = []
Prelude> filter' odd [1..10]
*** Exception: <interactive>:1:5-21: Non-exhaustive patterns in function filter'

在ghci中,用什么惯用方式来定义这种语法?在定义下面的子句之前,我不知道要为它们留出多少空格!关于:{}:,有没有更好的方法?

不要在ghci提示符下编写函数-将它们保存在MyFunctions.hs或其他文件中,然后执行以下操作

Prelude> :{
Prelude| let filter' p (x:xs)
Prelude|     | p x              = x : filter' p xs
Prelude|     | otherwise        = filter' p xs
Prelude| let filter' _ []       = []
Prelude| :}

<interactive>:2:5: parse error (possibly incorrect indentation)
在ghci

ghci中的let命令会删除以前的定义,因此当您执行此操作时

:l MyFunctions
实际上,您正在执行let-filter'px:xs | px=x:filter'pxs |否则=filter'pxs,然后完全删除该定义,将其替换为let-filter'.[]=[]

非穷举模式意味着您在[1..10]上使用了过滤器的第二个定义,它不是空的,您的第二个版本的过滤器只包含空列表


虽然filter px:xs | px=x:filter'pxs |否则=filter'pxs很难看,但您的定义很好,并且工作正常,没有缩进错误。我知道你想用ghci写一行,但是文本编辑器+ghci+是一个强大的组合
let filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs
let filter' _ [] = []

也就是说,ghci中的let表达式引入了一个新变量,并隐藏了旧定义。正如Andrew所建议的,只需将定义保存到文件中。

这里有两个问题。首先,使用多个let语句就是生成两个独立的定义,后者隐藏前者。第二,语法错误的原因是您没有对保护进行足够的缩进,即| px。。。行的缩进深度应大于过滤器的p x:xs

尽管将定义保存在文件中更简单,但以下是在GHCi中正确输入定义的方法

Prelude> let x = 1
Prelude> let x = 2
Prelude> x
2

:{和:}命令用于输入跨越多行的定义。对齐=是可选的,重要的是行的缩进。

正如其他答案所指出的,每次在GHCi中有一个新的let语句时,它都会覆盖以前的定义。但是,您仍然可以通过将定义放入一个let语句中来使用模式匹配。基本上有两种方法可以做到这一点

首先,只需使用分号:

Prelude> :{
Prelude| let filter' p (x:xs)
Prelude|      | p x       = x : filter' p xs
Prelude|      | otherwise = filter' p xs
Prelude|     filter' _ [] = []
Prelude| :}
其次,使用:{…:}和缩进

let filter' p [] = []; filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs
我省略了提示,以便更轻松地粘贴副本。

除了 , 您可以设置允许多行命令:

:{
let filter' _ [] = []
    filter' p (x:xs)
      | p x = x : filter' p xs
      | otherwise = filter' p xs
:}
您可以编写多行定义,之后不带:{和:}。 一条空行将完成一个块

Prelude> :set +m
如果要切换回单线模式,请运行unset:

然后,:r重新加载。另请参见
Prelude> let filter' p (x:xs)
Prelude|      | p x       = x : filter' p xs
Prelude|      | otherwise = filter' p xs
Prelude|     filter' _ [] = []
Prelude|
Prelude>
Prelude> :unset +m