Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
haskell,可以调试解析错误吗?_Haskell - Fatal编程技术网

haskell,可以调试解析错误吗?

haskell,可以调试解析错误吗?,haskell,Haskell,我正在做一些我在网上的一系列讲座中发现的练习,遇到了一个我无法克服的问题,本质上,我在一个文件中定义了一个函数 doubleEveryOtherHelper :: [Integer] -> Int -> [Integer] doubleEveryOtherHelper ((x:x1:xs) len) | len > 2 = x : 2*x1 : doubleEveryOtherHelper(xs (len - 1)) | len == 2 = x : 2*

我正在做一些我在网上的一系列讲座中发现的练习,遇到了一个我无法克服的问题,本质上,我在一个文件中定义了一个函数

doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper ((x:x1:xs) len)
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper(xs (len - 1))
    | len == 2 = x : 2*x1
    | len == 1 = [2*x]
    | otherwise = []
加载文件后,我得到以下信息(仅此):

无论函数在我加载时可能做什么或不做什么,是否有任何方法让ghci以人类可读的形式告诉我它试图解析的所有内容,以便我自己能够弄清楚这些事情(即,如果我能看到它试图解析的实际上是什么(可能是垃圾),与我所想的相反,它试图解析(一个函数名和两个参数:一个list和一个Int,然后根据len的值返回列表),然后修复它应该容易得多)


我现在只知道这是错误的。。。出于某种原因(即使某个善良的人告诉我我在这个例子中犯了什么错误,我也不想在将来再被如此微小的不同问题难倒。)

据我所知,没有办法强迫GHCI向您提供更多信息(尽管我承认自己不是一个非常有经验的GHCI用户)。哈斯克尔的错误可能非常隐晦,但识别和理解它们的能力将随着时间和经验而来。同时,我可以给你一些关于理解和纠正错误的提示:

  • Parse error
    这意味着GHCI无法理解代码的词典结构,无论您编写的代码应该做什么。分析错误的常见原因包括缩进不一致和分隔符不匹配,例如额外或缺少结束符
    。这让您知道您使用的顶级语法存在问题,具体来说:

  • 在模式中:
    既然您在代码中使用了它,我想您对它很熟悉。这让我们知道在模式表达式中使用的语法有问题。具体来说,围绕这一点:

  • (x:x1:xs)
    这是用于匹配两个或多个元素列表的有效模式。我们知道这个结构导致了一个错误,但是由于它本身是有效的,我们可以得出结论,这个模式导致了一个解析错误,因为它使用的是上下文

扩大我们的视野来观察整个模式,我们发现模式周围有一对无关的圆括号,正是这对圆括号将解析器抛出:

(   (x:x1:xs) len   ) --These should not be here
由于
(x:x1:xs)
len
不是同一数据结构的一部分,因此不应将它们放在括号中(在这方面,Haskell与许多语言不同,在这些语言中,函数调用中的所有参数都用括号括在一起)。删除这些括号可修复分析错误

doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper(xs (len - 1))
    | len == 2 = x : 2*x1
    | len == 1 = [2*x]
    | otherwise = []
…但揭示了大量其他错误,这些错误散布在我们现在的词典(但逻辑上不正确)函数中。调试愉快

编辑:把所有这些新错误都留给你似乎很不礼貌,所以我修正了它们。下面是一个可以正确编译的函数(尽管我还没有测试过它是否有效):

请注意,第3行和第4行可以写得更清楚:

 | len > 2  = [x, 2*x1] ++ doubleEveryOtherHelper xs (len - 1)
 | len == 2 = [x, 2*x1]

嗯,我知道你想要的是一个方法,而不是答案,但让我从答案开始……错误在于你添加了额外的括号。在定义的模式匹配端,parens的意思与右侧非常不同(即,它们的意思是“这里的所有内容都只匹配一个参数”).拆下外罩,问题就消失了

至于更广泛的问题,我实际上不知道关于如何查看语法期望值的答案,但如果它确实存在,它可能没有您认为的那么有用。解析错误是最基本的错误类型,只有当语言的语法不满足时才会触发。本质上,编译器不知道什么不满足o发生这种情况时,请务必这样做。从错误报告的角度来看,编译器真正能做的就是在错误发生时向您显示输入,并可能向您显示可能预期的值列表。后者的问题是,它往往过于冗长,没有真正的用处


不过,这里有一件事——解析错误是非常基本的,一旦你用这种语言写了一小段时间,它们就很容易被发现几乎从不分析错误。

其他人已经指出了分析错误。让我在此代码中添加一些逻辑错误,即使没有明确请求

-- Syntactically fixed code
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
    | len == 2 = x : 2*x1 : []
    | len == 1 = [2*x]
    | otherwise = []
我猜
len
参数应该是整数列表的长度


现在,模式
x:x1:xs
匹配第一个元素为
x
、第二个元素为
x1
的列表。因此,模式将永远不会匹配少于两个元素的列表。这意味着测试
len==1
时,尤其要注意对
doubleEver>的递归调用中的相同错误yOtherHelper
谢谢,这是一个非常有用的答案(并为我指出了我应该更详细地阅读的方向)。实际上,你不需要所有的括号:
x:2*x1:doubleEveryOtherHelper xs(len-1)
是可以的。另外,
x:[2*x1]
更常见的书写形式是
[x,2*x1]
@chi当然!我真不敢相信我错过了。谢谢,这是一种更清晰的表达方式。
|len>2=([x,2*x1]++doubleEveryOtherHelper xs)$(len-1)
可能不是您想要的……感谢这一点……在编译我的代码并进行播放后,我发现我所采用的方法不是真正的最佳方法,实际上我发现自己采用了与这里基本相同的方法(尽管
 | len > 2  = [x, 2*x1] ++ doubleEveryOtherHelper xs (len - 1)
 | len == 2 = [x, 2*x1]
-- Syntactically fixed code
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
    | len == 2 = x : 2*x1 : []
    | len == 1 = [2*x]
    | otherwise = []
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper []        len = ???
doubleEveryOtherHelper [x]       len = ???
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
    | len == 2 = x : 2*x1 : []
    | len == 1 = [2*x]
    | otherwise = []
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper []        len = []    -- was in the oterwise case
doubleEveryOtherHelper [x]       len = [2*x] -- was in the len==1 case
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2   = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
    | len == 2 = x : 2*x1 : []
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper []        len = []    -- was in the oterwise case
doubleEveryOtherHelper [x]       len = [2*x] -- was in the len==1 case
doubleEveryOtherHelper (x:x1:xs) len
    | len > 2  = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
    | len == 2 = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
doubleEveryOtherHelper :: [Integer] -> Int ->  [Integer]
doubleEveryOtherHelper []        len = []   
doubleEveryOtherHelper [x]       len = [2*x]
doubleEveryOtherHelper (x:x1:xs) len = x : 2*x1 : doubleEveryOtherHelper xs (len - 1)
doubleEveryOtherHelper :: [Integer] -> [Integer]
doubleEveryOtherHelper []        = []   
doubleEveryOtherHelper [x]       = [2*x]
doubleEveryOtherHelper (x:x1:xs) = x : 2*x1 : doubleEveryOtherHelper xs