3
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'

我错过了什么模式?

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 中定义这个(语法方面)的惯用方式是什么?排队是=怎么回事 - 在我定义它们之前,我不知道要为以下子句留多少空间!:{}: 是怎么回事,有更好的方法吗?

4

5 回答 5

10

这里有两个问题。首先,使用多个let语句是在做出两个独立的定义,后者遮蔽了前者。其次,语法错误的原因是你没有足够的缩进你的警卫(该| px ...行应该缩进比 更远filter' p (x:xs))。

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

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

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

于 2012-09-18T21:02:32.633 回答
4

不要在 ghci 提示符下编写函数 - 将它们保存在MyFunctions.hs或其他东西中并执行

:l MyFunctions

在 ghci 中。

letghci 中的命令会删除以前的定义,所以当你这样做时

let filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs
let filter' _ [] = []

您实际上是在let filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs完全删除该定义以将其替换为let filter' _ [] = [].

Non-exhaustive patterns意味着您在 [1..10] 上使用了不为空的过滤器的第二个定义,而您的过滤器的第二个版本仅涵盖空列表!

您的定义很好,效果很好,没有缩进错误,虽然filter'' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs很丑。我意识到你试图用 ghci 写一个单行,但是文本编辑器 + ghci + http://www.haskell.org/hoogle/是一个强大的组合!

于 2012-09-18T20:45:57.557 回答
1

要详细说明 Andrew 的答案,请考虑以下 ghci 会话。

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

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

于 2012-09-18T20:49:52.213 回答
1

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

首先,只需使用分号:

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
:}

(我省略了提示以便于复制粘贴。)

于 2012-09-18T21:02:33.847 回答
0

除了 Hammar's answer之外,您还可以设置“允许多行命令”:

Prelude> :set +m

您可以在没有:{:}之后编写多行定义。一个空行将完成一个块

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

如果要切换回单行模式,请运行unset

Prelude> :unset +m
于 2017-01-15T20:59:21.887 回答