Haskell 失败时如何保存信息?
我正在编写一些代码,使用Haskell 失败时如何保存信息?,haskell,monads,monad-transformers,state-monad,Haskell,Monads,Monad Transformers,State Monad,我正在编写一些代码,使用StateTmonad转换器跟踪一些有状态信息(日志记录等) 我要传递给StateT的monad非常简单: data CheckerError a = Bad {errorMessage :: Log} | Good a deriving (Eq, Show) instance Monad CheckerError where return x = Good x fail msg = Bad msg (Bad msg) >&g
StateT
monad转换器跟踪一些有状态信息(日志记录等)
我要传递给StateT的monad非常简单:
data CheckerError a = Bad {errorMessage :: Log} | Good a
deriving (Eq, Show)
instance Monad CheckerError where
return x = Good x
fail msg = Bad msg
(Bad msg) >>= f = Bad msg
(Good x) >>= f = f x
type CheckerMonad a = StateT CheckerState CheckerError a
它只是一个左
和右
变体
让我烦恼的是fail
的定义。在我的计算中,我在这个单子中产生了很多信息,即使失败了,我也希望保留这些信息。
目前,我唯一能做的就是将所有内容转换为字符串
,并使用字符串
作为参数传递给失败
创建一个坏
实例
我想做的是:
fail msg = do
info <- getInfoOutOfTheComputation
return $ Bad info
fail msg=do
信息您的检查错误单子与或单子非常相似。我将在回答中使用或单子(及其对应的单子转换器)
单子变换器有一个微妙之处:顺序很重要。“内部”单子的效果优先于“外部”层的效果。考虑这两个可供选择的定义:<代码> CukMunad < /C> >:
import Control.Monad.State
import Control.Monad.Error
type CheckerState = Int -- dummy definitions for convenience
type CheckerError = String
type CheckerMonad a = StateT CheckerState (Either String) a
type CheckerMonad' a = ErrorT String (State CheckerState) a
在CheckerMonad
中,或是内部单子,这意味着故障将擦除整个状态。请注意此运行函数的类型:
runCM :: CheckerMonad a -> CheckerState -> Either CheckerError (a,CheckerState)
runCM m s = runStateT m s
您要么失败,要么返回一个结果以及到该点为止的状态
在CheckerMonad'
中,状态是内部单子。这意味着即使在发生故障的情况下,状态也将保持不变:
runCM' :: CheckerMonad' a -> CheckerState -> (Either CheckerError a,CheckerState)
runCM' m s = runState (runErrorT m) s
返回一对,其中包含到该点的状态以及失败或结果
这需要一点实践来培养如何正确订购单声道变压器的直觉。本节中的图表是一个很好的起点
另外,最好避免直接使用,因为它被认为是语言中的一个小缺点。相反,使用由错误转换器提供的用于抛出错误的专用函数。使用的error
或其他实例时,请使用
sillycomp::CheckerMonad'Bool
sillycomp=do
修改(+1)
s runCM’sillycomp 2
加载包变压器-0.3.0.0。。。链接。。。完成。
加载包mtl-2.1.2。。。链接。。。完成。
(左“boo”,3)
*Main>runCM’sillycomp 3
(正确,正确,4)
error
有时使用起来很烦人,因为与或不同,它需要对错误类型进行约束。Error
typeclass强制您定义两个错误构造函数noMsg
和strMsg
,这对您的类型可能有意义,也可能没有意义
您可以改为使用包中的,它允许您使用任何类型作为错误。使用时,使用left
函数抛出错误。简短回答:这不是fail
的目的,所以它当然不起作用。@Carl然后告诉我应该如何实现这一点。我想要的是:1)一种在发生不好的事情时“停止”计算的方法2)保留在该点之前生成的有状态信息。我看到的所有能够实现1的示例都使用fail
,而无法实现2。目前我唯一想到的是:prettyFail=do statefail
只是作为一种权宜之计来支持do表示法中的模式匹配失败。
sillycomp :: CheckerMonad' Bool
sillycomp = do
modify (+1)
s <- get
if s == 3
then throwError "boo"
else return True
*Main> runCM' sillycomp 2
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package mtl-2.1.2 ... linking ... done.
(Left "boo",3)
*Main> runCM' sillycomp 3
(Right True,4)