Haskell初学者无法匹配预期的类型

时间:2015-04-27 18:58:32

标签: haskell maybe either

我需要编写一个程序来解码一个包含四个值的列表,这些值可以是I或O到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)) 列表中。我知道我必须使用,但我根本无法绕过它。现在我完全绝望了,因为我根本无法解决这个问题。

示例输入和输出可能如下所示:[I,O,O,I] => [左,对,错]

这是我目前的代码:

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.

这些是我得到的错误:

.row

现在任何,这有助于我解决这个问题,这是值得欢迎的。我已经尝试过这一天的大部分时间,我根本无法解决它。

1 个答案:

答案 0 :(得分:5)

您需要在Just语句前添加case,才能将这些值转换为Maybe [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],但要使用++,您只需要[Either Bool Bool] ++仅适用于列表。这就是Maybe monad派上用场的地方:

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-ifs的另一种方式。我还使用模式匹配来避免head!!tail的所有用法,因为通常应该避免使用这些函数(它们调用error而不是正确的错误处理使用Maybe)。如果返回<-Maybe的{​​{1}}语法将提前退出计算,因此Nothing与说end <- decode rest相同。然后,不是在case / ifs的每个分支中构建整个结果,而是从if isNothing (decode rest) then Nothing else <continue>x计算单个结果,然后在结尾处构建结果列表。