我尝试制作一个非常短的代码,因为我们有一个有利于最短代码的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 '='
<{1>}上的。
我认为可以在where块中定义多个函数吗?
其他缩进创建了很多错误
line "b = head ys"
或
not in scope 'a'
not in scope 'b'
not in scope 'c'
not in scope 'd'
我必须以这种方式保存一些令牌/使用更短的代码。
答案 0 :(得分:2)
你有一个比缩进更基本的问题:where
块是单功能案例的本地。您正尝试使用where
块向一大堆函数提供绑定(例如a
,b
,c
,d
)。这不起作用。
为了澄清,这个正确缩进的代码将不起作用:
foo :: Int -> Int
foo 0 = a
foo 1 = b
where a = 2
b = 3
您会收到Not in scope: `a'
之类的错误。这是因为where
仅延伸到foo 1
案例;它甚至没有进入foo 0
情况,更不用说任何其他功能了。
另一方面,您的代码似乎希望where
块可用于所有您的函数。要拥有不同功能可以看到的绑定,您必须将它们放在与功能本身相同的范围内。
另外,Haskell缩进有点吝啬。你真的应该避免标签;让编辑器正确理解Haskell也很有帮助。我发现Emacs在这里非常好 - 我从来不用担心Emacs的Haskell缩进。
Emacs可能有一点学习曲线(你应该做教程),但我认为这是值得的。您还必须安装Haskell模式。如果您获得最新版本的Emacs,您应该可以使用包管理器执行此操作。
答案 1 :(得分:2)
这就是它对编译器的看法:
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
子句仅限于最后一个等式,因此a, b, c, d
的前四个等式中没有func
范围。
答案 2 :(得分:0)
您的错误消息是因为您正在混合制表符和空格。最好只使用空格。
现在,如果你正在写
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]
现在 更短。