简体   繁体   English

我对 Haskell 有一个错误,我找不到我的情况

[英]Im having an error with Haskell with cases that i cant find

So im trying to create this function AgregarMon that basically adds a "Monomio" to "Polinomio" Monomio would end up being an element inside Polinomio which is a list.所以我试图创建这个 function AgregarMon,它基本上向“Polinomio”添加了一个“Monomio”,Monomio 最终会成为 Polinomio 中的一个元素,它是一个列表。 You are going to understand better in a little bit你会更好地理解一点点

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;}}}}

I've been looking at my code like an hour, and i cant find the problem.我一直在看我的代码一个小时,但我找不到问题。 The error says:错误说:

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;    |                                                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

Line 45 is the fourth line on the code from above.第 45 行是上面代码的第四行。 Im sorry if im missing info, please let me now.对不起,如果我缺少信息,请让我现在。 Just in case, someone doesnt knows, fst and snd are on the Prelude.以防万一,有人不知道,fst 和 snd 在 Prelude 上。 fst takes the first element from a "Monomio" snd the second one. fst 从“Monomio”中获取第一个元素,然后获取第二个元素。 fst = (a,b)->a snd (a,b) -> b fst = (a,b)->a snd (a,b) -> b

While you can, in a pinch, use curly brackets and semicolons, Haskell isn't a C-based language.虽然您可以在紧要关头使用大括号和分号,但 Haskell 不是基于 C 的语言。 It idiomatically uses indentation to indicate function scope.习惯性地使用缩进来表示 function scope。

Something like this would be more idiomatic:这样的事情会更惯用:

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

This compiles (although with warnings, see below), but I don't know if it does what you want it to do.这可以编译(尽管有警告,见下文),但我不知道它是否符合您的要求。 The OP code doesn't compile, so clearly something that does compile isn't equivalent. OP 代码不编译,所以很明显,编译的东西是等价的。

All I did, however, was to remove all the curly brackets and semicolons, and instead 'fix' the indentation.然而,我所做的只是删除所有大括号和分号,而是“修复”缩进。

The code is still, in my opinion, too indented, but at least (with one exception) it stays left of 80 characters.在我看来,代码仍然缩进太多,但至少(有一个例外)它保持在 80 个字符的左边。 Wide code could force people to scroll horizontally, which isn't going to make you many friends.宽代码可能会迫使人们水平滚动,这不会让你交到很多朋友。

The above code loads in GHCi, but with warnings:上面的代码在 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.

Thus, I'm not sure that it works as intended.因此,我不确定它是否按预期工作。

The version of Mark Seemann can be improved though. Mark Seemann 的版本虽然可以改进。

Firstly, let's make m and p actual arguments of agregarMon :首先,让我们将mp设为 agregarMon 的实际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

Now we can use pattern matching on agruments to simplify code:现在我们可以在 agruments 上使用模式匹配来简化代码:

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

It is not so idiomatic to pattern-match with case a result of condition check, better use if or guards:通过条件检查的结果与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

Now we have some simple cases and a complex one, but even the complex one is not so hard to read and understand (I even made an assumption that you're working with polynomials, coefficients and powers).现在我们有一些简单的案例和一个复杂的案例,但即使是复杂的案例也不难阅读和理解(我什至假设您正在使用多项式、系数和幂)。

You can run it there: https://repl.it/@Yuri12358/so-monomio-polinomio你可以在那里运行它: https://repl.it/@Yuri12358/so-monomio-polinomio

Maybe this link will help you to improve your understanding of different ways to make branching in your code: http://learnyouahaskell.com/syntax-in-functions#pattern-matching也许此链接将帮助您提高对在代码中进行分支的不同方法的理解: http://learnyouahaskell.com/syntax-in-functions#pattern-matching

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

is wrong: true here is just a variable name, unrelated to the constructor True (with a capital T .).错了:这里的true只是一个变量名,与构造函数True无关(大写T 。)。 The snippet above is therefore equivalent to因此,上面的代码片段等价于

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

Hence, the pattern matches any boolean value, True and False .因此,该模式匹配任何 boolean 值TrueFalse For that reason the other branch false ->... will never be considered.因此,永远不会考虑另一个分支false ->...

I recommend you turn on warnings, since doing so makes GHC report the second branch as redundant code.我建议您打开警告,因为这样做会使 GHC 将第二个分支报告为冗余代码。 The fact that the compiler considers a branch useless signals that something is very wrong with the code.编译器认为分支无用的事实表明代码存在严重问题。

As a final note, in my experience code like最后一点,在我的经验代码中

case something of
  True  -> a
  False -> b

is not common, since we can write it as并不常见,因为我们可以把它写成

if something
then a
else b

which is easier to read, in my view.在我看来,这更容易阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM