0

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

它在输入“appendString”中显示解析错误,但我认为它没有任何问题......

我从 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"

你知道我哪里做错了吗?

编辑:添加了整个区域

4

2 回答 2

3

Haskellif不像ifJava 或 python 中的其他。最大的区别是它们是表达式,不像 java 或 python 中它们是语句。

它们更接近于condition ? res1 : res2来自 C.

编写嵌套 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 ....

这看起来更具可读性。

于 2013-04-10T04:53:15.830 回答
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 = ...
于 2013-04-10T05:19:27.180 回答