输入'appendString'Haskell上的Parse Error

时间:2013-04-10 04:23:29

标签: haskell

嘿伙计们,所以这是一个奇怪的小错误,我得到了,我不明白为什么它给了我。

它表示输入'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"

你看到我在哪里出错吗?

编辑:添加整个区域

2 个答案:

答案 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,否则我们继续condition2otherwise始终为真。为你

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 = ...