如何在Haskell中将IO添加到我自己的monad中?

时间:2011-09-16 09:55:01

标签: haskell

我是Haskell的新手。我写了自己的monad,它是状态monad,有错误处理:

newtype MyMonad a = MyMonad (State -> Either MyError (State, a))

我在一个小语言的翻译中使用它。现在我想在我的语言中添加一些IO操作(读/写),但我不知道如何在我的内部包含IO monad。我知道我可以将ErrorT,StateT,IO结合起来并实现这个结果但是没有它们还有其他方法吗?

1 个答案:

答案 0 :(得分:6)

您可以查看StateT的实施方式:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

要将状态与IO合并,您只需IO代替m并获取所需类型:s -> IO (a,s)

如果您也有错误,这会变成s -> IO (Either e (a, s))s -> IO (Either e a, s),具体取决于您是否希望失败的计算影响状态。

请注意,如果没有时间机器,您无法使s -> Either e (IO (a, s))成为monad

<强>更新

事实证明,即使使用时间机器,你也无法成为一个单子。

为了说明为什么不可能,让我们首先使用()代替s来简化我们的monad:data M e a = M { runM :: Either e (IO a) }

现在,想象一下以下程序:

unsafePerformIO :: IO a -> a
unsafePerformIO io = fromLeft $ runM $ do
  a <- M $ Right $ io
  M $ Left a

显然,这个函数是不可能的,因此M的monad实例也是不可能的。

机器可以给你的时间是能够像对待IO一样对待State。但是,我没有意识到Either e (s -> (a, s))不是monad。