我感到困惑的是,編譯器不會抱怨下面的代碼(代碼編譯):爲什麼顯然任何monad棧通常會派生MonadIO?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main where
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Except (ExceptT)
main = undefined
newtype Foo e m a = Foo { unFoo :: ExceptT e m a }
deriving (Functor, Applicative, Monad, MonadIO)
,將立即意義的,我再說一次,如果我不得不添加MonadIO m
爲約束的地方,例如
deriving instance MonadIO m => MonadIO (Foo e m a)
而事實上,如果我嘗試
deriving instance MonadIO (Foo e m a),
編譯器會抱怨。
我也注意到,當我在那裏添加約束MonadIO m
時,我只能使用liftIO
,不管我是否將方法二與獨立派生和約束一起使用,這又是有道理的。在MonadIO m
的條件下的MonadIO
實例是。
這只是我,還是那種反直覺?
它是否與棄用的-XDatatypeContexts擴展有關?
我是知道的。但爲什麼這樣做太笨拙了?例如。當我導出'MonadError e'時,我不必在稍後添加任何約束。 –
''MonadError e''不需要'm'的任何約束,因爲使用'ExceptT'的實現,它適用於所有'm'。 'MonadIO'不能在沒有'm'約束的情況下實現,因爲它必須使用'm'中的實現,從而確保這種實現存在。它不是尷尬的,或者最不重要的就是它應該是尷尬的。 –
添加了文檔鏈接並希望有更好的解釋。 – Koterpillar