Haskell 具有函数 parseTimeM
,它取代了已弃用的 parseTime
函数。我想前者比后者更受欢迎的原因是它在报告解析错误方面具有更好的灵 active 。它可以在封闭的 monad 上调用 fail
,而不是 Maybe
。
所以我尝试了一下。首先,已弃用的函数:
> 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 ()
吗?如何像我想象的那样解析时间,即如果要解析的字符串格式不正确,则优雅地返回错误?
最佳答案
Except
是 mtl
的一部分,它是一个 monad 转换器库。转换器的常见风格是为某些行为定义转换器(在本例中为 ExceptT
),并将基本版本表示为类型同义词:
type Except e = ExceptT e Identity
所以你可能会遇到异常,因为 Except
的 fail
必须经过其小 monad 底部的 Identity
monad变压器堆栈。
具体而言,对于Except e
,您如何为任意类型e
实现fail
?由于我们对 e
一无所知,因此我们不能仅根据给定的字符串想象出 e
的值,因此 fail
必须给你一个异常或永远循环。
所有这些都是一个很好的论据,反对依赖 Monad
类中的 fail
的 parseTimeM
风格。
关于parsing - 如何正确使用Haskell的 `parseTimeM`函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30114318/