1

I または O のいずれかである 4 つの値のリストを のリストにデコードするプログラムを作成する必要があります[Either Bool Bool]。おそらく使用する必要があることはわかっていますが、頭を包むことはできません。私はこの問題を解決することができないので、今、私は完全に絶望的です.

入力と出力の例は次のようになります: [I,O,O,I] => [Left True, Right False]

ここに私が持っている現在のコードがあります:

module Blueprint where
import Prelude
import Data.Maybe

data Bit = O | I  deriving (Eq, Show)

encode :: [Either Bool Bool] -> [Bit]
encode [] = []
encode l  = case head l of
            Left  False -> [I, I] ++ encode (tail l)
            Left  True  -> [I, O] ++ encode (tail l)
            Right False -> [O, I] ++ encode (tail l)
            Right True  -> [O, O] ++ encode (tail l)

decode :: [Bit] -> Maybe [Either Bool Bool]
decode []   = Nothing
decode [x]  = Nothing
decode l = if isNothing (decode (tail (tail l)))
  then Nothing
  else case  head l of
    I -> if l!!1 == I
          then [Left False]  ++ decode (tail (tail l))
          else [Left True]  ++ decode (tail (tail l))
    O -> if l!!1 == I
          then [Right False]  ++ decode (tail (tail l))
          else [Right True] ++ decode (tail (tail l))

これらは私が得るエラーです:

Prelude> :load serialise
[1 of 1] Compiling Blueprint        ( serialise.hs, interpreted )

serialise.hs:22:16:
    Couldn't match expected type `Maybe [Either Bool Bool]'
                with actual type `[Either Bool b0]'
    In the expression: [Left False] ++ decode (tail (tail l))
    In the expression:
      if l !! 1 == I then
          [Left False] ++ decode (tail (tail l))
      else
          [Left True] ++ decode (tail (tail l))
    In a case alternative:
        I -> if l !! 1 == I then
                 [Left False] ++ decode (tail (tail l))
             else
                 [Left True] ++ decode (tail (tail l))

serialise.hs:22:33:
    Couldn't match expected type `[Either Bool b0]'
                with actual type `Maybe [Either Bool Bool]'
    In the second argument of `(++)', namely `decode (tail (tail l))'
    In the expression: [Left False] ++ decode (tail (tail l))

serialise.hs:23:16:
    Couldn't match expected type `Maybe [Either Bool Bool]'
                with actual type `[Either Bool b1]'
    In the expression: [Left True] ++ decode (tail (tail l))
    In the expression:
      if l !! 1 == I then
          [Left False] ++ decode (tail (tail l))
      else
          [Left True] ++ decode (tail (tail l))
    In a case alternative:
        I -> if l !! 1 == I then
                 [Left False] ++ decode (tail (tail l))
             else
                 [Left True] ++ decode (tail (tail l))

serialise.hs:23:32:
    Couldn't match expected type `[Either Bool b1]'
                with actual type `Maybe [Either Bool Bool]'
    In the second argument of `(++)', namely `decode (tail (tail l))'
    In the expression: [Left True] ++ decode (tail (tail l))

serialise.hs:25:16:
    Couldn't match expected type `Maybe [Either Bool Bool]'
                with actual type `[Either a0 Bool]'
    In the expression: [Right False] ++ decode (tail (tail l))
    In the expression:
      if l !! 1 == I then
          [Right False] ++ decode (tail (tail l))
      else
          [Right True] ++ decode (tail (tail l))
    In a case alternative:
        O -> if l !! 1 == I then
                 [Right False] ++ decode (tail (tail l))
             else
                 [Right True] ++ decode (tail (tail l))

serialise.hs:25:34:
    Couldn't match expected type `[Either a0 Bool]'
                with actual type `Maybe [Either Bool Bool]'
    In the second argument of `(++)', namely `decode (tail (tail l))'
    In the expression: [Right False] ++ decode (tail (tail l))

serialise.hs:26:16:
    Couldn't match expected type `Maybe [Either Bool Bool]'
                with actual type `[Either a1 Bool]'
    In the expression: [Right True] ++ decode (tail (tail l))
    In the expression:
      if l !! 1 == I then
          [Right False] ++ decode (tail (tail l))
      else
          [Right True] ++ decode (tail (tail l))
    In a case alternative:
        O -> if l !! 1 == I then
                 [Right False] ++ decode (tail (tail l))
             else
                 [Right True] ++ decode (tail (tail l))

serialise.hs:26:32:
    Couldn't match expected type `[Either a1 Bool]'
                with actual type `Maybe [Either Bool Bool]'
    In the second argument of `(++)', namely `decode (tail (tail l))'
    In the expression: [Right True] ++ decode (tail (tail l))
Failed, modules loaded: none.

現在、この問題を解決するのに役立つものは何でも大歓迎です。私は一日の大部分でこれを試しましたが、単に解決できません。

4

1 に答える 1

5

これらの値を単に ではなく に変換するにはJust、ステートメントの前にを配置する必要があります。caseMaybe [Either Bool Bool][Either Bool Bool]

decode :: [Bit] -> Maybe [Either Bool Bool]
decode []   = Nothing
decode [x]  = Nothing
decode l = if isNothing (decode (tail (tail l)))
  then Nothing
  else Just $ case head l of
    I -> if l!!1 == I
          then [Left False]  ++ decode (tail (tail l))
          else [Left True]  ++ decode (tail (tail l))
    O -> if l!!1 == I
          then [Right False]  ++ decode (tail (tail l))
          else [Right True] ++ decode (tail (tail l))

しかし、これですべてが解決するわけではありません。またdecode、その計算に埋め込まれており、その型は ですMaybe [Either Bool Bool]が、使用するにはasだけ++が必要で、リストでのみ機能します。ここでモナドが役に立ちます:[Either Bool Bool]++Maybe

decode [] = Nothing
decode [x] = Nothing
decode (x:y:rest) = do
    end <- decode rest
    let this = case (x, y) of
            (I, I) -> Left False
            (I, O) -> Left True
            (O, I) -> Right False
            (O, O) -> Right True
    return (this : end)

ここでの case ステートメントは、実際には、case/nested-if を記述する別の方法にすぎません。また、パターン マッチングを使用して、head!!、およびのすべての使用を回避しましたtail。これらの関数は通常回避する必要があるためです (これらの関数は、errorを使用して適切なエラー処理を行う代わりに呼び出しますMaybe)。の<-構文は、 が返されたMaybe場合に計算を早期に終了するため、 と言っているのと同じです。次に、case/ifs の各分岐で結果全体を構築する代わりに、とから単一の結果を計算し、最後に結果リストを構築します。Nothingend <- decode restif isNothing (decode rest) then Nothing else <continue>xy

于 2015-04-27T19:02:38.810 に答える