哪里的缩进不正确?短代码



我试图制作一个非常短的代码,因为我们有一个支持最短代码的reglementation。我们必须创建一个函数,将列表按相同顺序转换为升序和降序的新列表:例如。[1,6,2,1,7,3,2,8,4]变为[[1,6],[2,1],[7],[3,2],[8],[4]]

所以我试着做以下事情:

func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys    | a >= b = d `f1` a:ys
| otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys    | a < b = d `f2` a:ys
| otherwise = c : d `f1` [a]
where   a = head xs
b = head ys
c = reverse ys
d = tail xs

但我有

parse error on input '=' 

在CCD_ 3上。

我认为可以在where块中定义多个函数?

其他压痕会产生错误,比如很多

not in scope 'a'
not in scope 'b'
not in scope 'c'
not in scope 'd'

parse error on input 'b'

我必须这样做才能保存一些令牌/拥有更短的代码。

编译器就是这样看的:

func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys    | a >= b = d `f1` a:ys
| otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys    | a < b = d `f2` a:ys
| otherwise = c : d `f1` [a]
where    a = head xs
b = head ys
c = reverse ys
d = tail xs

因此,对于编译器来说,where子句中第一行之后的行看起来像是该行的延续,当然,如果一行上没有分号,就不可能有多个=

您应该永远不要混合制表符和空格(实际上,您永远不应该使用制表符)。如果您使用制表符,请将编辑器配置为将它们解释为八个空格。

而且,where子句只作用于最后一个方程,因此在func的前四个方程中,作用域中没有a, b, c, d

您有一个比缩进更基本的问题:where块是单个函数用例的本地块。您正试图使用where块为一整组函数提供绑定(例如abcd)。这行不通。

为了澄清,这个正确缩进的代码不起作用:

foo :: Int -> Int
foo 0 = a
foo 1 = b
where a = 2
b = 3

您将得到类似Not in scope: `a'的错误。这是因为CCD_ 15仅在CCD_;它甚至不涉及foo 0的情况,更不用说任何其他函数了。

另一方面,您的代码似乎期望where块适用于所有函数。要使绑定能够被不同的函数看到,必须将它们与函数本身放在同一级别的作用域中。

此外,Haskell缩进有点芬尼克。你真的应该避免标签;拥有一个能够正确理解Haskell的编辑器也确实很有帮助。我发现Emacs在这里非常好——我永远不必担心Emacs的Haskell缩进。

Emacs可能有一点学习曲线(你应该做教程),但我认为这是值得的。你还必须安装Haskell模式。如果您获得了Emacs的最新版本,那么您应该能够使用包管理器来完成这项工作。

您的错误消息是因为您混合了制表符和空格。最好只是利用空间。

现在,如果你在写

a = head xs
b = head ys
c = reverse ys
d = tail xs

然后

xs = (a:ds)
ys = (b:es)

让我们用模式匹配重写您的函数:

func :: Ord a => [a] -> [[a]]
func [] = []
func (a:ds) = f1 ds [a]
f1 [] ys = [reverse ys]
f1 (a:ds) (b:es) | a >= b = ds `f1` (a:b:es)
| otherwise = reverse (b:es): ds `f2` [a]
f2 [] ys = [reverse ys]
f2 (a:ds) (b:es) | a < b = ds `f2` (a:b:es)
| otherwise = reverse (b:es) : ds `f1` [a]

我知道这更长,但请耐心等待。f1f2确实一样,只是比较有所改变。让我们得到一个函数no来否定比较,这样(no (>=)) x y = not (x >= y):

no cmp x y = not (cmp x y)

事实上,我们可以把它写成

no = ((not.).)
r = reverse
func' (a:ds) = f (>=) ds [a]
f :: Ord a => (a -> a -> Bool) -> [a] -> [a] -> [[a]]
f _ [] ys = [r ys]
f cp (a:ds) ys@(b:es) | cp a b = f cp ds (a:ys)
| True = r ys : f (no cp) ds [a]

现在更短了。