2013-04-10 80 views
0

嘿家伙,所以这是一个奇怪的小错误,我得到了,我不明白为什么它给了我。解析错误输入'appendString'Haskell

它说,在输入解析错误“appendString”但我认为没有错吧......

我把它从若,然后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" 

你看到我可能出错了吗?

编辑:增加了整个区域

+1

,请复制粘贴代码 – jozefg 2013-04-10 04:38:54

+0

全断面虽然它无关,你问的错误,你需要'currentIndex-1'的括号。 – hammar 2013-04-10 04:40:52

+0

添加了完整部分 – 2013-04-10 04:42:31

回答

3

哈斯克尔if的不是像其他if“中说Java或Python秒。最大的区别是他们是表达式不像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始终为true。对你而言

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

看起来更具可读性。

+0

谢谢!这完全有效,并帮助我理解为什么我缩排错误。 – 2013-04-10 05:00:08

0

这里有一个重构::

createShow currentIndex [email protected](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说清楚它不是总计函数。当它结束时会发生什么?
  • 使用[email protected]来命名模式。这样,在进行递归调用时,您不需要“重构”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 = ...