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

5 time parsing haskell

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

所以我尝试了一下。首先,不推荐使用的函数:

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

> parseTime defaultTimeLocale  "%Y" "201x" :: Maybe UTCTime
Nothing
Run Code Online (Sandbox Code Playgroud)

伟大的。正如预期的那样。然后,Identity单子:

> 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"
Run Code Online (Sandbox Code Playgroud)

也是预料之中的,因为Identitymonad 没有优雅的故障模式。但是,我期望 monad 有所不同Except,其目的是优雅地捕获错误。

> 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"
Run Code Online (Sandbox Code Playgroud)

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

Tik*_*vis 3

Except是 的一部分mtl,它是一个 monad 转换器库。变压器的常见风格是为某些行为定义变压器(ExceptT在本例中)并将基本版本表示为类型同义词:

type Except e = ExceptT e Identity
Run Code Online (Sandbox Code Playgroud)

因此,您可能会遇到异常,因为failforExcept必须经过Identity其小 monad 转换器堆栈底部的 monad。

具体来说,Except e您将如何实现任意fail类型?由于我们对 完全一无所知,因此我们不能仅仅想出给定字符串的值,因此必须您一个异常或永远循环。eeefail

所有这些都是反对课堂上parseTimeM依赖的风格的一个很好的论据。failMonad