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

Haskellは、たとえば Java や python のif他の とは異なります。if最大の違いは、ステートメントである Java や Python とは異なり、式であるということです。

condition ? res1 : res2それらはfrom Cに非常に近いです。

ネストされた if を記述する正しい方法は次のとおりです。

if condition
  then foo
  else if condition2
         then bar
         else ...

これがひどく醜いことに気付くでしょう。

そのため、haskell にはガードがあります。

foo args | condition = foo
         | condition2= bar
         | otherwise = meh

ここで関数を宣言し、 true の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 ....

これははるかに読みやすいように見えます。

于 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は、1 回しか呼び出されないため、取り除かれ、一番上に移動され、インライン化されています。
  • 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これらの引数を what take の最後に配置し、それらを因数分解することも一般的なイディオムです。

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 に答える