Haskell中的类型安全`read`

时间:2014-05-26 02:21:54

标签: haskell

Learn You a Haskell讨论了以下数据类型:

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday   
           deriving (Eq, Ord, Show, Read, Bounded, Enum)  

本书演示了如何使用read将字符串解析为Day类型。

$ read "Saturday" :: Day
Saturday

但是,我可以传入非Day值,导致异常。

$ read "foo" :: Day
*** Exception: Prelude.read: no parse

在上面的示例中,使用read的类型安全方式是什么?

2 个答案:

答案 0 :(得分:12)

除了@JonPurdy提到的旧标准功能reads之外,还有最近添加的

Text.Read.readMaybe :: Read a => String -> Maybe a

当字符串只包含一个要解析的值时,它更容易使用。

答案 1 :(得分:10)

您可以使用reads,它会为您提供一组已解析的值和未解析的余数:

reads :: Read a => ReadS a
type ReadS a = String -> [(a, String)]

现在你可以明确地匹配结果并做你喜欢的事情:

case reads x of

  -- foo
  [] -> Left "no parse"

  -- Saturday
  [(day, "")] -> Right (day :: Day)

  -- Fridayum
  [(_, junk)] -> Left $ "day followed by extra junk: " ++ junk

  _ -> Left "ambiguous parse"

虽然老实说我估计GHC运行时的例外成本会降低......

对于更复杂的事情,您可以使用(例如)Parsec:

编写解析器
day :: Parser Day
day = choice
  [ Monday <$ string "Monday"
  , ...
  ] <* eof

无论你选择哪个解析库,都会有运行解析器和处理解析错误的方法,比如Parsec的parse