我试图制作一个非常短的代码,因为我们有一个支持最短代码的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
块为一整组函数提供绑定(例如a
、b
、c
、d
)。这行不通。
为了澄清,这个正确缩进的代码不起作用:
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]
我知道这更长,但请耐心等待。f1
和f2
确实一样,只是比较有所改变。让我们得到一个函数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]
现在更短了。