它表示输入'appendString'中的Parse Error但我发现它没有错......
我从if,then else语句中调用它如下:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
if currentIndex ==0 || dir == 2
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex+1 (Grid {delta = d, middle = (x,y), points = g}) 2 (counter+1))
else if counter == (2*d+1)
then (appendString d (x,y) g currentIndex) ++ (appendX x)
else if dir == 1
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex-1 (Grid {delta = d, middle = (x,y), points = g}) 1 (counter+1))
其中createShow返回一个字符串,appendString
也是如此appendString在构造函数中给出错误:
appendString d (x,y) g currentIndex =
(if currentIndex == y
then "y "
else
" " ) ++ (show currentIndex) ++(rowFunction g x d 0 (x+d) 1)++ "\n"
你看到我在哪里出错吗?
编辑:添加整个区域
答案 0 :(得分:3)
Haskell if
与Java或python中的其他if
不同。最大的区别是它们是表达式,不像java或python,它们是语句。
它们更接近于C的condition ? res1 : res2
。
编写嵌套if的正确方法是这样的:
if condition
then foo
else if condition2
then bar
else ...
你会注意到这是非常难看的。
这就是为什么haskell有警卫:
foo args | condition = foo
| condition2= bar
| otherwise = meh
这里我们声明一个函数foo
,如果condition
为真,那么我们执行foo
,否则我们继续condition2
,otherwise
始终为真。为你
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter
| currentIndex == 0 || dir == 2 = appendString d ....
| counter == (2 * d + 1) = appendString d ....
| dir == 1 = appendString d ....
看起来更具可读性。
答案 1 :(得分:0)
这是重构::
createShow currentIndex grid@(Grid {delta = d, middle = (x,y), points = g}) dir counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine
where
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine | currentIndex == 0 || dir == 2 = createShow (currentIndex+1) grid 2 (counter+1)
nextLine | counter == (2*d+1) = appendX x
nextLine | dir == 1 = createShow (currentIndex-1) grid 1 (counter+1)
appendX x = ...
需要注意的事项:
where
子句通常可以避免重复参数appendString
的常见调用已被排除,并移至顶部,然后内联,因为它只被调用一次。nextLine
中的警卫更清楚地处理级联if
。nextLine
的警卫和表格清楚地表明它不是总功能。什么会在它结束时发生?grid@
命名模式。这样,在进行递归调用时,您无需“重建”Grid
值。人们可以走得更远。注意到Grid {...}
和dir
在整个功能中从未发生变化,这表明将这些因素排除在外:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
line currentIndex counter
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...
在这里,line
扮演“携带”部分围绕唯一的值,这些值随着函数的递归而不同。将这些论点放在createShow
所采用的结尾处是一种常见的习惯,因此甚至将它们排除在外:
createShow :: Grid -> Int -> Int -> Int -> String
createShow (Grid {delta = d, middle = (x,y), points = g}) dir = line
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...