【问题标题】:Haskell produces non exhaustive patterns errorHaskell 产生非详尽模式错误
【发布时间】:2013-02-08 06:49:24
【问题描述】:

所以我决定玩弄 Haskell。我正在尝试解决 Project Euler 的第一个问题。以下是我的代码:

     euler1 limit (div:divisors) = if limit > 1 then (euler1 limit divisors) + (euler1 limit (div:[])) + (euler1 (limit-1) (div:divisors)) else 0
     euler1 limit (divisor:[]) = if limit > 1 && (mod limit divisor) == 0 then limit else 0
     euler1 limit [] = 0

但是,当我通过 ghci 运行它时,会发生以下情况:

     euler1 9 [3,5]
     *** Exception: <interactive>:3:5-90: Non-exhaustive patterns in function euler1

进一步调试:

     euler1 5 []
     0

     euler1 5 [5]
     *** Exception: <interactive>:3:5-90: Non-exhaustive patterns in function euler1

这表明损坏的代码属于第二种情况(包含一个元素的列表),其中 euler1 甚至不包含递归步骤。

怎么了?为什么它会如此壮观地破裂?我错过了什么模式? (我有单元素列表,多元素列表和空列表没有?)

编辑:对于任何关心我最初在上面提供的解决方案(在 John L 的出色帮助下)的人来说,仍然不太正确,因为它会多次计算一个除数以上的倍数的项目。最终的、正确的、有效的算法如下:

       euler1 limit (divisor:[]) = if ((limit > 1) && ((mod limit divisor) == 0)) then limit else 0
       euler1 limit (div:divisors) | ((limit > 1) && (euler1 limit (div:[]))==0) = (euler1 limit divisors) + (euler1 (limit-1) (div:divisors)) | ((limit > 1) && (euler1 limit (div:[]))/=0) = (euler1 limit (div:[])) + (euler1 (limit-1) (div:divisors)) |limit > 1 = euler1 (limit-1) (div:divisors) | otherwise = 0
       euler1 limit [] = 0

【问题讨论】:

    标签: haskell


    【解决方案1】:

    你是在 ghci 中定义这个吗?如果你这样做:

    Prelude> let euler1 limit (divisor:[]) = if limit > 1 && (mod limit divisor) == 0 then limit else 0
    Prelude> let euler1 limit [] = 0
    

    第二个定义会影响第一个,导致非穷举模式失败。

    相反,您应该使用 ghci 的多行语法

    Prelude> :{
    Prelude| let euler1 limit (divisor:[]) = if limit > 1 && (mod limit divisor) == 0 then limit else 0
    Prelude|     euler1 limit (div:divisors) = if limit > 1 then (euler1 limit divisors) + (euler1 limit (div:[])) + (euler1 (limit-1) (div:divisors)) else 0
    Prelude|     euler1 limit [] = 0
    Prelude| :}
    

    还请注意,我交换了前两个语句的顺序。 div:divisors 将匹配一个单元素列表,因此您需要先检查该特殊情况。

    【讨论】:

    • 谢谢!我永远不会发现这个! (我相当确定我的 if 条件/mod 调用中有某种语法错误)xD
    • @AbrahamP 将函数保存在文件 Euler.hs 中并在 ghci 中执行 :l Euler.hs 来加载它真的值得,这比直接在 ghci 中编写要容易得多。
    • @AndrewC 我同意,我几乎总是这样工作。但是多行表示法在其他情况下很方便,而且知名度不高,所以趁机宣传一下。
    • @JohnL 哦,绝对 - 它确实非常方便。喜欢。
    • 感谢我在 :load 上度过了一段无聊的时光,并且在我继续进行更深入的研究/问题等之前只是使用 ghci 进行修补(其中在行等方面进行空间分隔的能力将是绝对的)必要)让我的头脑围绕语法等。但是,是的,我已经把它改写成一个更易读的文件格式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多