当我在ghci中编译我的代码时,没有问题。它可以正确编译。但是,如果我尝试在拥抱中编译它,我会收到错误“编译代码太复杂”。我认为问题是由于许多|
条件造成的。
如果我将其更改为使用if / else,则没有问题。我可以添加if / else语句100次,但这将非常烦人和恼人。而不是那样,我试图在20-30 |
条件之后放置if / else语句,但如果语句如下所示我无法使|
工作:
f x y z
| cond1 = e1
| cond2 = e2
...
if (1)
then
| cond30 = e30
| cond31 = e31
...
else
| cond61 = e61
| cond62 = e62
如何以最省力的方式修复代码?完整代码在hpaste上,因为它比StackOverflow的问题大小限制更长。
答案 0 :(得分:9)
首先,你可以重写
function input
| this && that && third thing && something else = ... -- you only actually needed brackets for (head xs)
| this && that && third thing && something different = ....
| this && that && a change && ...
...
| notthis && ....
与
function input | this = function2 input'
| notthis = function4 input'
function2 input | that = function3 input''
| notthat = ...
这应该简化你的200行copo
代码,但这仍然是错误的方法。
处理您经常处理的操作的4个案例可以用一个函数替换,可能像:
operation :: Num a => Char -> a -> a -> a
operation x = case x of
'+' -> (+)
'-' -> (-)
'*' -> (*)
'/' -> (/)
_ -> error ("operation: expected an operation (+-*/) but got " ++ [c])
你应该使用一些标准函数来帮助减少所有单个字符检查,只需抓取尽可能多的数字。 takeWhile :: (a -> Bool) -> [a] -> [a]
,所以
takeWhile isDigit "354*243" = "354"
takeWhile isDigit "+245" = ""
并且有相应的dropWhile
:
dropWhile isDigit "354*1111" = "*1111"
dropWhile isDigit "*1111" = "*1111"
因此,最明显的缩短代码就是用
开始代码copo xs = let
numText = takeWhile isDigit xs
theRest = droWhile isDigit xs
num = read numText
....
in answer....
但是如果你想要takeWhile
和dropWhile
这两个名为span
,则有一个快捷方式,因为span p xs == (takeWhile p xs, dropWhile p xs)
copo xs = let
(numText,theRest) = span isDigit xs
num = read numText
....
in answer....
您处理234
然后234*56
然后234*56/23
然后....
您可以使用递归调用copo
来替换它,或者生成一棵树。这取决于你是否应该服从正常的运算符优先级(*或/在+或 - 之前)。
答案 1 :(得分:0)
如果你坚持守卫,而不是
foo a b c d
| cond1, cond2, cond3 = ...
| cond1, cond2, cond4 = ...
| cond5, cond6, cond7 = ...
| cond5, cond6, cond8 = ...
写
foo a b c d
| cond1, cond2 = case () of
() | cond3 = ...
| cond4 = ...
| cond5, cond6 = case () of
() | cond7 = ...
| cond8 = ...