缩进的位置不正确?短代码

时间:2012-11-10 18:45:32

标签: haskell where-clause shortcode

我尝试制作一个非常短的代码,因为我们有一个有利于最短代码的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'

我必须以这种方式保存一些令牌/使用更短的代码。

3 个答案:

答案 0 :(得分:2)

你有一个比缩进更基本的问题:where块是功能案例的本地。您正尝试使用where块向一大堆函数提供绑定(例如abcd)。这不起作用。

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

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]

我知道这个更长,但请耐心等待。 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]

现在 更短。