将字符串解析为数据类型:更好的错误消息?

Parsing string into data type : better error messages?

目前我正在使用以下方法将字符串解析为数据类型 来自 Text.Readread 函数,如 下面的例子:

module Main where

data Inner = Inner { x :: Int , y :: Double } deriving (Read,Show)
data Outer = Outer { inner :: Inner } deriving (Read,Show)

parseOuter :: Outer
parseOuter = read "Outer { inner = Inner { x = 4, y = 4.5 } }"

main = do
  print parseOuter
  --output : Outer {inner = Inner {x = 4, y = 4.5}}

但是错误信息不是很好。例如,如果 我通过 x = 4.3 不小心把 x 变成了 Double 然后我 得到下面程序中显示的错误消息:

module Main where

data Inner = Inner { x :: Int , y :: Double } deriving (Read,Show)
data Outer = Outer { inner :: Inner } deriving (Read,Show)

parseOuter :: Outer
parseOuter = read "Outer { inner = Inner { x = 4.3 , y = 4.5 } }"

main = do
  print parseOuter
  --output : *** Exception: Prelude.read: no parse

haskell 中是否有功能允许我 执行上述操作但错误消息更好?

如果你只想要更优雅的错误处理,你可以使用

import Text.Read

parseOuter :: Maybe Outer
parseOuter = readMaybe "Outer { inner = Inner { x = 4, y = 4.5 } }"

main :: IO ()
main = do
  case parseOther of
    Just x  -> print x
    Nothing -> putStrLn "parse error"

对于更严重的错误处理,我会使用像 parsec 这样的合适的解析库。 Parsec 提供 <?> 运算符来用有用的错误消息装饰解析器:例如如果发生解析错误,myParser <?> "foo" 将生成诸如 "expected foo" 的消息。