2

我试图制作一个非常短的代码,因为我们有一个偏爱最短代码的规则。我们必须创建一个函数,以相同的顺序将列表转换为升序和降序列表的新列表:例如。[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 '=' 

line "b = head ys"

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

其他缩进会产生很多错误

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

或者

parse error on input 'b'

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

4

3 回答 3

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,您应该可以使用包管理器来执行此操作。

于 2012-11-10T18:52:56.637 回答
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, dfunc

于 2012-11-10T18:53:18.073 回答
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]

现在短了。

于 2012-11-10T21:38:10.553 回答