Haskell 变量不在范围内:a

Haskell 变量不在范围内:a,haskell,scope,pattern-matching,mergesort,Haskell,Scope,Pattern Matching,Mergesort,我正在尝试制作一个简单的合并排序函数。代码即将完成,但是: m_sort :: (Ord a) => [a] -> [a] m_sort d | d == [] = [] | d == [a] = [a] | otherwise = merge (m_sort (fst $ split d)) (m_sort (snd $ split d)) 出于某种原因,我在这里得到了Haskell_培训。hs:137:21:error:Variable不在范围内:

我正在尝试制作一个简单的合并排序函数。代码即将完成,但是:

m_sort :: (Ord a) => [a] -> [a]
m_sort d
     | d == [] = []
     | d == [a] = [a]
     | otherwise = merge (m_sort (fst $ split d)) (m_sort (snd $ split d))
出于某种原因,我在这里得到了Haskell_培训。hs:137:21:error:Variable不在范围内:a。排除| d==[a]=[a]会导致很好的编译,但没有它就无法工作。模式匹配是否存在一些我没有看到的明显问题

模式匹配是否存在一些我没有看到的明显问题


是的,当然:你还没有写一个模式匹配!好的,你写了一个简单的,d,它匹配任何东西,并命名为d。你写的是一个守卫,它必须是Bool类型的表达式。虽然d==[a]在语法上是正确的,如果d和a有适当的类型,可能会有类型Bool,但在这里它不起作用,因为您没有任何a来比较d

你可能想要这个:

m_sort [] = []
m_sort [a] = [a]
m_sort d = merge ...
现在,不再使用一个表达式,其中的术语[a]引用某个名为a的变量,而是一个模式匹配,它查找一个具有单元素列表形状的术语,并将a绑定到该元素

模式匹配是否存在一些我没有看到的明显问题


是的,当然:你还没有写一个模式匹配!好的,你写了一个简单的,d,它匹配任何东西,并命名为d。你写的是一个守卫,它必须是Bool类型的表达式。虽然d==[a]在语法上是正确的,如果d和a有适当的类型,可能会有类型Bool,但在这里它不起作用,因为您没有任何a来比较d

你可能想要这个:

m_sort [] = []
m_sort [a] = [a]
m_sort d = merge ...

现在,这将是一个模式匹配,而不是一个表达式中有[a]这个词,它引用了一个名为a的变量,它将查找一个具有一个元素列表形状的术语,并将a绑定到该元素。

Iirc,这不是模式匹配-您要问的是d是否等于[a],你还没有定义什么是导致问题的原因

请记住,您需要一个表达式作为保护中的条件来计算Bool,因此像lengthd==1这样的表达式应该可以工作:

m_sort :: (Ord a) => [a] -> [a]
m_sort d
     | d == []        = []
     | length d  == 1 = d
     | otherwise      = merge (m_sort (fst $ split d)) (m_sort (snd $ split d))

或者,您可以将函数声明为多个片段,我认为这是更好的实践,正如@DanielWagner的回答,这将允许您像尝试一样使用模式匹配。

Iirc,这不是模式匹配-您询问的是d是否等于[a],并且您还没有定义导致问题的a是什么

请记住,您需要一个表达式作为保护中的条件来计算Bool,因此像lengthd==1这样的表达式应该可以工作:

m_sort :: (Ord a) => [a] -> [a]
m_sort d
     | d == []        = []
     | length d  == 1 = d
     | otherwise      = merge (m_sort (fst $ split d)) (m_sort (snd $ split d))

或者,您可以将函数声明为多个片段,我认为这是更好的实践,如@DanielWagner的回答,这将允许您像尝试一样使用模式匹配。

您可能需要类似null的内容。tail$d而不是length d,因为length需要评估整个列表,而我们只关心它是否有多个元素。@puhlen Oooh,很好-我不会编辑,因为我认为length更清晰,效率可能不太重要,但是+1,所以他们希望看到更有效的方法。在这种情况下,正确的模式匹配是最好的方法,这只是希望解释为什么OP当前的方法不起作用。长度很清楚,但效率很低。可能有一个比我的建议更好的方法,因为这只是我的想法,但无论如何我都会使用模式匹配。如果我需要像这样的长度检查,我可能会为它编写一个适当命名的函数,如果它还不存在的话,这样我就可以既清晰又高效。tail$d而不是length d,因为length需要评估整个列表,而我们只关心它是否有多个元素。@puhlen Oooh,很好-我不会编辑,因为我认为length更清晰,效率可能不太重要,但是+1,所以他们希望看到更有效的方法。在这种情况下,正确的模式匹配是最好的方法,这只是希望解释为什么OP当前的方法不起作用。长度很清楚,但效率很低。可能有一个比我的建议更好的方法,因为这只是我的想法,但无论如何我都会使用模式匹配。如果我需要像这样的长度检查,我可能会为它编写一个适当命名的函数,如果它还不存在的话,这样我就可以既清晰又高效。谢谢,令人惊讶的是,lengthd==1和lengthd==a之间的差异在我之前解决的30多个问题中从来都不重要,所以我很幸运地发现了这一点。这可能是一个很大的误会future@AndrewS. 我觉得你的评论有点令人困惑。长度d==1和长度d==a是非常显著的不同;而且我的回答根本没有提到长度!一个guard,它必须是Bool类型的表达式-技术上为false,因为@user2407038好的,这是公平的。我不确定在那里添加精确的语言是否会使解释更准确
不过,我认为答案的力量更好,所以我将留下它,并对你的评论进行投票,以鼓励感兴趣的读者深入研究精确的规则。感谢你,令人惊讶的是,在我解决的30多个问题中,lengthd==1和lengthd==a之间的差异从来都不重要,所以我很幸运地偶然发现了这一点。这可能是一个很大的误会future@AndrewS. 我觉得你的评论有点令人困惑。长度d==1和长度d==a是非常显著的不同;而且我的回答根本没有提到长度!一个guard,它必须是Bool类型的表达式-技术上为false,因为@user2407038好的,这是公平的。但是,我不确定添加精确的语言会使答案的解释力更好,因此我将留下它并对您的评论进行投票,以鼓励感兴趣的读者深入了解精确的规则。d==[a]不是模式匹配的a表达式,因此它当然可能不会绑定变量。您可能希望|[a]d==[a]不是模式匹配的a表达式,因此它当然可能不会绑定变量。你可能想要|[a]