Haskell在我找不到的情况下出错

问题描述 投票:1回答:3

[因此,我试图创建此功能AgregarMon,该功能基本上是将“ Monomio”添加到“ Polinomio”Monomio最终将成为Polinomio内部的一个列表元素。您将稍微了解一点]

type Monomio = (Int, Int)
type Polinomio = [Monomio]

agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon = \m p -> case m of{ (0,0) -> p;
                                 x -> case p of{[] -> [x];
                                                y:ys -> case (snd x == snd y) of { true -> case ((fst x + fst y)==0) of { true -> ys;
                                                                                                                          false -> (fst x + fst y , snd x):ys;}
                                                                                   false -> case snd x < snd y of{true -> y: agregarMon x ys;
                                                                                                                  false -> x:y:ys;}}}}

我一直在看我的代码,就像一个小时,但我找不到问题。错误说:

Polinomios.hs:45:140: error:
    Unexpected case expression in function application:
        case ((fst x + fst y) == 0) of
          true -> ys
          false -> (fst x + fst y, snd x) : ys
    You could write it with parentheses
    Or perhaps you meant to enable BlockArguments?
   |
45 |                                                                                                 y:ys -> case (snd x == snd y) of { true -> case ((fst x + fst y)==0) of { true -> ys;    |                                                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

第45行是代码上方的第四行。对不起,如果我缺少信息,请现在让我。以防万一,有人不知道,fst和snd在前奏中。 fst从“ Monomio”中获取第一个元素,然后从第二个元素获取。 fst =(a,b)-> a snd(a,b)-> b

function haskell recursion switch-statement haskell-prelude
3个回答
0
投票

虽然您可以在紧急情况下使用大括号和分号,但Haskell并不是基于C的语言。 idiomatically uses indentation表示功能范围。

类似的东西会更惯用:

agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon = \m p -> case m of
                      (0,0) -> p
                      x -> case p of
                            [] -> [x]
                            y:ys -> case (snd x == snd y) of
                                      true -> case ((fst x + fst y)==0) of
                                                true -> ys
                                                false -> (fst x + fst y , snd x):ys
                                      false -> case snd x < snd y of
                                                true -> y: agregarMon x ys
                                                false -> x:y:ys

这会编译(尽管有警告,请参阅下文),但是我不知道它是否可以完成您想要的工作。 OP代码不会编译,因此显然[编译的内容是不等效的。

但是,我要做的只是删除所有大括号和分号,而是“修复”了缩进。

我认为代码仍然缩进,但至少(除了一个例外)它保留了80个字符。宽代码可能会迫使人们水平滚动,这不会使您成为很多朋友。

以上代码在GHCi中加载,但带有警告:

[1 of 1] Compiling Q58986486 ( 58986486.hs, interpreted ) 58986486.hs:14:49: warning: [-Woverlapping-patterns] Pattern match is redundant In a case alternative: false -> ... | 14 | false -> (fst x + fst y , snd x):ys | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58986486.hs:15:39: warning: [-Woverlapping-patterns] Pattern match is redundant In a case alternative: false -> ... | 15 | false -> case snd x < snd y of | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... 58986486.hs:17:49: warning: [-Woverlapping-patterns] Pattern match is redundant In a case alternative: false -> ... | 17 | false -> x:y:ys | ^^^^^^^^^^^^^^^ Ok, one module loaded.

因此,我不确定它是否按预期工作。

0
投票
Mark Seemann的版本可以改进。

首先,让mp成为agregarMon的实际参数:

agregarMon :: Monomio -> Polinomio -> Polinomio agregarMon m p = case m of (0,0) -> p x -> case p of [] -> [x] y:ys -> case (snd x == snd y) of true -> case ((fst x + fst y)==0) of true -> ys false -> (fst x + fst y , snd x):ys false -> case snd x < snd y of true -> y: agregarMon x ys false -> x:y:ys

现在我们可以在模式上使用模式匹配来简化代码:

agregarMon :: Monomio -> Polinomio -> Polinomio agregarMon (0, 0) p = p agregarMon x [] = [x] agregarMon (f, s) (y:ys) = case (snd x == snd y) of true -> case ((fst x + fst y)==0) of true -> ys false -> (fst x + fst y , snd x):ys false -> case snd x < snd y of true -> y: agregarMon x ys false -> x:y:ys

条件检查的结果与case进行模式匹配并不是那么习惯,最好使用if或警卫:

agregarMon :: Monomio -> Polinomio -> Polinomio agregarMon (0, 0) p = p agregarMon x [] = [x] agregarMon x@(coefx, powx) (y@(coefy, powy):ys) | powx == powy = if coefx + coefy == 0 then ys else (coefx + coefy, powx):ys | powx < powy = y:agregarMon x ys | otherwise = x:y:ys

现在我们有一些简单的情况和一个复杂的情况,但是即使是复杂的情况也不是很难阅读和理解的(我什至假设您正在使用多项式,系数和幂)。

您可以在此处运行它:https://repl.it/@Yuri12358/so-monomio-polinomio

也许此链接将帮助您提高对代码分支的不同方法的理解:http://learnyouahaskell.com/syntax-in-functions#pattern-matching


0
投票
case (snd x == snd y) of { true ->
是错误的:true这里只是一个变量名,与构造函数True不相关(大写字母T!)。因此,以上代码段等同于

case (snd x == snd y) of { x ->

因此,模式匹配任何布尔值TrueFalse。因此,将不再考虑其他分支false -> ...

我建议您打开警告,因为这样做会使GHC将第二个分支报告为冗余代码。编译器认为分支无用这一事实表明,代码存在某些问题。

© www.soinside.com 2019 - 2024. All rights reserved.