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

Haskell 缩进哪里不正确?短代码,haskell,where-clause,shortcode,Haskell,Where Clause,Shortcode,我试图编写一个非常短的代码,因为我们有一个支持最短代码的regelementation。 我们必须创建一个函数,该函数将一个列表转换为一个新的升序列表和降序列表,顺序相同:例如。[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 =

我试图编写一个非常短的代码,因为我们有一个支持最短代码的regelementation。 我们必须创建一个函数,该函数将一个列表转换为一个新的升序列表和降序列表,顺序相同:例如。[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
在b线上=头部ys

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

其他缩进会产生错误,比如很多

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


我必须这样做以保存一些令牌/缩短代码。

您有一个比缩进更基本的问题:其中块是单个函数用例的局部块。您试图使用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,您应该能够使用软件包管理器来实现这一点。

您有一个比缩进更基本的问题: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,您应该能够使用软件包管理器执行此操作。

编译器就是这样认为的:

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子句中的行看起来像是该行的延续,当然,如果一行中没有分号,就不能有multiple=

你不应该混合使用制表符和空格,事实上,你不应该使用制表符。如果使用制表符,请将编辑器配置为将其解释为八个空格


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

编译器就是这样认为的:

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子句中的行看起来像是该行的延续,当然,如果一行中没有分号,就不能有multiple=

你不应该混合使用制表符和空格,事实上,你不应该使用制表符。如果使用制表符,请将编辑器配置为将其解释为八个空格


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

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

现在,如果你在写

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

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

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]
事实上,我们可以这样写

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]

现在缩短了。

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

现在,如果你在写

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

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

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]
事实上,我们可以这样写

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]

现在缩短了。

选项卡?如果是,用火杀死他们。谁要你这么短的代码,为什么?标签?如果是,用火杀死他们。谁向你要这么短的代码,为什么?@AndrewC:哈哈,我指的是标签,不是空格。抢手货最后,如果可以避免的话,你应该避免手动缩进:。@AndrewC:Haha,我是说制表符,不是
空间。抢手货最终,如果可以避免的话,您应该避免手动缩进内容:。有趣的解决方案,我想到了一个将f函数打包成一个的解决方案,更改比较,但无法解决它,因为我只是一个初学者。^^谢谢你。啊,我刚刚发现,我必须更改>=到=到<和不到OK,传递一个Bool,而不是a->a->Bool,并使用not代替no。接下来用| leq cp a b替换防护装置| cp a b,并分别定义leq True==。最后,func a:ds=f False ds[a]。有趣的解决方案,我想到了一个将f函数打包成一个的解决方案,改变了比较,但无法解决它,因为我只是一个初学者。^^谢谢你。啊,我刚刚发现,我必须更改>=到=到<和不到OK,传递一个Bool,而不是a->a->Bool,并使用not代替no。接下来用| leq cp a b替换防护装置| cp a b,并分别定义leq True==。最后,func a:ds=f False ds[a]。我不得不说,我编辑了stackoverflow的缩进,因为它没有正确显示。因此编译器的代码看起来有点不同。但现在我知道我不必使用制表符,而且where不能用于多个函数。我不得不说,我编辑了stackoverflow的缩进,因为它没有正确显示。因此编译器的代码看起来有点不同。但现在我知道我不必使用选项卡,而且不能用于多个功能。