我需要编写一个程序来解码一个包含四个值的列表,这些值可以是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
现在任何,这有助于我解决这个问题,这是值得欢迎的。我已经尝试过这一天的大部分时间,我根本无法解决它。
答案 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
计算单个结果,然后在结尾处构建结果列表。