无法将预期类型“[foo]”与实际类型“Maybe [foo]”相匹配

Couldn't match expected type ‘[foo]’ with actual type ‘Maybe [foo]’

我有两种记录类型:

data Attribute = Attr {
    attName  :: Text,
    attValue :: Text
} deriving (Show, Generic)

data Attributes = Attrs {
    attributes :: [Attribute]
} deriving (Show, Generic)

main 中,contents 值包含一个 Maybe [Attribute],我正试图将其铲入 Attrs 构造函数中:

main :: IO ()
main = do
    bytes <- readFile "data/file.json"
    contents <- pure (decode bytes :: Maybe [Attribute])
    let attributes = Attrs { attributes = contents }
    print attributes

运行 这会产生以下错误:

• Couldn't match expected type ‘[Attribute]’
              with actual type ‘Maybe [Attribute]’
• In the ‘attributes’ field of a record
  In the expression: Attrs {attributes = contents}

somethingMaybe [Attribute] 而不是直接 [Attribute] 时如何应用 Attrs { attributes = something } 构造函数?

您需要处理解码失败的 Nothing 情况。这是一种可行的方法。

main :: IO ()
main = do
    bytes <- readFile "data/file.json"
    case decode bytes :: Maybe [Attribute] of
       Nothing -> putStrLn "Error: can't decode the file!"
       Just contents -> do
          let attributes = Attrs { attributes = contents }
          print attributes

:: Maybe [Attribute] 部分可能是多余的,因为编译器可以从程序的其余部分推断出该类型。不过,您可能希望将其保留在那里以使代码对人类更具可读性。

注意decode库函数被设计为returnMaybe [Attribute]而不是[Attribute]这样既可以报错(解码失败)也可以force调用者处理此类错误。这样程序员就不会再“忘记”检查错误,因为类型不匹配。

如果 decode 没有这样做,decode 将需要使程序崩溃(非常不方便)或报告一个虚拟值(例如 []),这可能是误认为是实际输入,并允许调用者忘记检查错误。

如果你想过危险的生活:

let Just contents = (decode bytes :: Maybe [Attribute])