【问题标题】:How to add IO to my own monad in Haskell?如何在 Haskell 中将 IO 添加到我自己的 monad?
【发布时间】:2011-09-16 09:55:00
【问题描述】:

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

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

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

【问题讨论】:

    标签: haskell


    【解决方案1】:

    你可以看看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

    更新

    事实证明,即使使用时间机器,您也无法将其变成 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 -&gt; (a, s)) 不是单子。

    【讨论】:

    • 时光机?你能提供一些上下文吗?这是一些“双关语”的笑话,还是一些高级数学/编程科学术语?
    • 这里没有双关语,我说的是实时机器。一旦你有了它,你就可以实现这个 monad。
    • @Rotsor: 解释一下为什么说时间机器是必需的?
    • 时间机器没用。
    • 时间机器永远帮不上忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 2016-08-12
    • 2011-08-20
    • 1970-01-01
    • 2023-04-05
    • 2019-07-31
    • 1970-01-01
    相关资源
    最近更新 更多