我是Haskell的新手。我寫我自己的單子是國家單子錯誤處理:如何將IO添加到Haskell中的我自己的monad中?
newtype MyMonad a = MyMonad (State -> Either MyError (State, a))
我用它在一個小語種的翻譯。現在我想將一些IO操作添加到我的語言中(讀/寫),但我不知道如何在我的內部封裝IO monad。我知道我可以結合ErrorT,StateT,IO並實現這個結果,但有沒有其他方法可以做到這一點?
我是Haskell的新手。我寫我自己的單子是國家單子錯誤處理:如何將IO添加到Haskell中的我自己的monad中?
newtype MyMonad a = MyMonad (State -> Either MyError (State, a))
我用它在一個小語種的翻譯。現在我想將一些IO操作添加到我的語言中(讀/寫),但我不知道如何在我的內部封裝IO monad。我知道我可以結合ErrorT,StateT,IO並實現這個結果,但有沒有其他方法可以做到這一點?
你可以看一下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))
單元
。
更新
事實證明,你不能讓它即使有時間機器單子。
說明爲什麼它是不可能的,讓我們通過使用()
代替s
第一簡化我們的單子: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。
時光機?你能提供一些背景嗎?這是一些「雙關語」的笑話,還是一些高級的數學/編程科學術語? – Tarrasch
這裏沒有雙關語,我正在談論一個真正的時間機器。一旦你有了它,你可以實現這個monad。 – Rotsor
@Rotsor:謹慎地解釋*爲什麼*說時間機器是必需的? – ivanm