如何正确使用Haskell的`parseTimeM`函数?

时间:2015-05-08 01:25:15

标签: parsing haskell time

Haskell具有函数parseTimeM,它取代了已弃用的parseTime函数。我认为前者优先于后者的原因是因为它在报告解析错误方面具有更好的灵活性。可以在封闭的monad上调用Maybe而不是fail

所以我试了一下。首先,弃用的功能:

> parseTime defaultTimeLocale  "%Y" "2015" :: Maybe UTCTime
Just 2015-01-01 00:00:00 UTC

> parseTime defaultTimeLocale  "%Y" "201x" :: Maybe UTCTime
Nothing

大。正如所料。然后,Identity monad:

> runIdentity $ parseTimeM  False defaultTimeLocale  "%Y" "2015" :: UTCTime
2015-01-01 00:00:00 UTC

> runIdentity $ parseTimeM  False defaultTimeLocale  "%Y" "201x" :: UTCTime
*** Exception: parseTimeM: no parse of "201x"

同样可以预料到,因为Identity monad没有优雅的故障模式。但是,我期望与Except monad有所不同,其目的是优雅地捕获错误。

> runExcept $ parseTimeM  False defaultTimeLocale  "%Y" "2015" :: Either () UTCTime
Right 2015-01-01 00:00:00 UTC

> runExcept $ parseTimeM  False defaultTimeLocale  "%Y" "201x" :: Either () UTCTime
*** Exception: parseTimeM: no parse of "201y"

为什么要抛出异常?它不应该返回Left ()吗?我如何解析我认为应该的时间,如果要解析的字符串格式不正确,那么优雅地返回错误?

1 个答案:

答案 0 :(得分:3)

Exceptmtl的一部分,它是monad变换器库。变换器的通常样式是为某些行为定义变换器(在本例中为ExceptT)并将基本版本表示为类型同义词:

type Except e = ExceptT e Identity

所以你可能会遇到异常,因为fail的{​​{1}}必须通过其小monad变换器堆栈底部的Except monad。

具体针对Identity,您如何为任意类型Except e实施fail?由于我们对e一无所知,因此我们不能在给定字符串的情况下设想e的值,因此e拥有给你一个例外或永远循环。

所有这些都是针对fail类中依赖parseTimeM的{​​{1}}风格的一个很好的论据。