2

Haskell コードに問題があります。次のような問題があります。

takeMeHere cs m =
    |(find (==E) cs == Nothing && (checkNextStep pozxCrt+1 pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt pozyCrt-1 m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep pozxCrt-1 pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt pozyCrt+1 m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
where
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

checkNextStep x y m = if(find (== (x,y)) m == Nothing) then True
   else False

を取得しparse error on input "|"ます。if then else if then のようなコードを書くと、うまくいきます。しかし、私は|を使いたい よりコンパクトなコーディングのために。ここで何が問題になっているようですか?

4

2 に答える 2

7

To fix parsing error, remove = from first line. The = sign is put after the guards.

Next, you should indent "where"

takeMeHere cs m
    |(find (==E) cs == Nothing && (checkNextStep pozxCrt+1 pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt pozyCrt-1 m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep pozxCrt-1 pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt pozyCrt+1 m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
  where
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

This will at least parse, yet it won't compile. The (checkNextStep pozxCrt pozyCrt+1 m) should be (checkNextStep pozxCrt (pozyCrt+1) m).

Let me add that you can fix a lot of verbose code:

  • find (==E) cs == Nothing can be changed to E `notElem` x
  • You do not need to compare with True: change x == True to x
  • if x then True else False can be changed to x
  • [x]++y can be changed to x:y
  • You can use pattern matching like this: (pozxCrt, pozyCrt) = head m or (pozxCrt, pozyCrt):_ = m

The result is:

takeMeHere cs m                                                                 
    | E `notElem` cs && checkNextStep (pozxCrt+1) pozyCrt m = (Just E,(pozxCrt+1,pozyCrt):m)
    | S `notElem` cs && checkNextStep pozxCrt (pozyCrt-1) m = (Just S,(pozxCrt,pozyCrt-1):m)
    | W `notElem` cs && checkNextStep (pozxCrt-1) pozyCrt m = (Just W,(pozxCrt-1,pozyCrt):m)
    | N `notElem` cs && checkNextStep pozxCrt (pozyCrt+1) m = (Just N,(pozxCrt,pozyCrt+1):m)
    | otherwise = (Nothing,m)                                                   
  where                                                                         
    (pozxCrt, pozyCrt) = head m                                                 

checkNextStep x y m = (x,y) `notElem` m

You have a lot of repetition in the guards. A lot of repetition is a sign to create new functions.

move E (x, y) = (x+1, y) 
move S (x, y) = (x, y-1)
move N (x, y) = (x, y+1)
move W (x, y) = (x-1, y)

takeMeHere cs m
    | canGo E = go E
    | canGo S = go S
    | canGo W = go W
    | canGo N = go N
    | otherwise = (Nothing,m)
  where
    pos = head m
    canGo dir = dir `notElem` cs && checkNextStep (move dir pos) m
    go dir = (Just dir, move dir pos:m)

checkNextStep (x, y) m = (x,y) `notElem` m

Next step: use find canGo [E,S,W,N] to get rid of the guards:

 takeMeHere cs m =                                                               
    case find canGo [E,S,W,N] of                                                
      Just dir -> (Just dir, move dir pos:m)                                    
      Nothing -> (Nothing, m) 
    where ...
于 2012-04-15T11:34:18.713 に答える
3

あなたのコードには少なくとも 3 つのエラーがあります。

  • =最初の行の を削除する必要があります。この構文では、=各 のガードの後に​​ が必要|です。基本的に、エラーは、最初のパイプ記号がその位置でガードなしで使用されて|いるため、後で予期しないことを示しています。=
  • 関数への入力で数式を与える場合は、数式を括弧で囲む必要があり+ます。は(明らかにエラーです)checkNextStep pozxCrt+1 pozyCrt mとして評価され、 としてではありません。(checkNextStep pozxCrt) + (1 pozyCrt m)checkNextStep (pozxCrt+1) pozyCrt m
  • where、最初の行に対してインデントする必要があります。

省略したコードに他のエラーがない限り、次のように動作するはずです。

takeMeHere cs m    -- no more "=" here
    |(find (==E) cs == Nothing && (checkNextStep (pozxCrt+1) pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt (pozyCrt-1) m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep (pozxCrt-1) pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt (pozyCrt+1) m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
  where -- indentation
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

ところで、あなたのコードは非常に冗長です。これらすべての比較について何かを行う必要がありますTrue(質問に対する @dbaupp のコメントを参照してください)。Haskell の演算子の優先順位と構文をもう少し勉強することをお勧めします。コードを読みやすくするのに大いに役立ちます :)

于 2012-04-15T11:23:38.303 に答える