所以我试图创建这个函数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
case (snd x == snd y) of { true ->
是错误的:true
这里只是一个变量名,与构造函数True
无关(带有大写T
!因此,上面的代码片段等效于
case (snd x == snd y) of { x ->
因此,该模式匹配任何布尔值,True
和False
。因此,永远不会考虑其他分支false -> ...
。
我建议您打开警告,因为这样做会使 GHC 将第二个分支报告为冗余代码。编译器认为分支无用的事实表明代码存在严重问题。
最后一点,在我的经验中,代码像
case something of
True -> a
False -> b
不常见,因为我们可以将其写为
if something
then a
else b
在我看来,这更容易阅读。
虽然你可以在紧要关头使用大括号和分号,但Haskell不是一种基于C的语言。它习惯性地使用缩进来指示函数范围。
像这样的东西会更惯用:
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.
因此,我不确定它是否按预期工作。
Mark Seemann的版本可以改进。
首先,让我们m
并p
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