2016-01-27 81 views
2

我已經問了這個問題here,但我想我會嘗試這樣做。如何將MonadLogger添加到我的免費monad變壓器堆棧中?

如何將MonadLogger添加到這個免費的monad變壓器堆棧中?

newtype Craft a = Craft { unCraft :: ReaderT CraftEnv (FreeT CraftDSL IO) a } 
    deriving (Functor, Monad, MonadIO, Applicative 
      , MonadReader CraftEnv, MonadFree CraftDSL, MonadThrow) 

我能夠沒有問題地添加MonadThrow;我希望加入MonadLogger會一樣容易。

我嘗試添加它,我得到這個錯誤:如果我定義一個實例

No instance for (MonadLogger (FreeT CraftDSL IO)) 
    arising from the 'deriving' clause of a data type declaration 

instance MonadLogger (FreeT CraftDSL IO) where 
    monadLoggerLog a b c d = Trans.lift $ monadLoggerLog a b c d 

我得到這個錯誤:

Could not deduce (MonadLogger IO) 
    arising from a use of ‘monadLoggerLog’ 

Here是一個鏈接我正在編寫的基本範例。

+1

你想如何使用IO進行日誌記錄?顯然沒有IO的例子,所以你必須自己寫。如果你想*實際上*將它添加到你的類型中,那麼你應該在這種情況下添加另一個圖層 - LoggerT。 – user2407038

回答

2

添加LoggingT進棧的基礎工程向右走,而是從

No instance for (MonadLogger (FreeT CraftDSL IO)) arising from the 'deriving' clause of a data type declaration

你想在你的DSL做塊記錄的東西判斷。爲此,我們需要做的FreeTMonadLogger例如:

instance (MonadLogger m, Functor f) => MonadLogger (FreeT f m) where 
    monadLoggerLog loc source level msg = lift $ monadLoggerLog loc source level msg 

由於LoggingT已經成爲MonadLogger的情況下,(MonadLogger m) => MonadLogger (FreeT f m)約束適用於您的Craft類型。

此代碼爲我編譯,但由於您沒有提供最小的測試用例,我不確定它是否真的有效。

+0

謝謝!這正是我需要的。這是我所有連接管道的例子。 https://github.com/joehillen/craft-monadfree/blob/loggingt/app/Main.hs –

0

添加LoggingT到變壓器堆棧,即

newtype Craft a = Craft { unCraft :: ReaderT CraftEnv (LoggingT (FreeT CraftDSL IO)) a } 
    deriving (Functor, Monad, MonadIO, Applicative 
      , MonadReader CraftEnv, MonadFree CraftDSL, MonadThrow, MonadLogger) 

,或者如果你需要DSL的解釋記錄:

newtype Craft a = Craft { unCraft :: ReaderT CraftEnv (FreeT CraftDSL (LoggingT IO)) a } 

如果有遺漏的情況下,那麼你需要手動把它們寫,因爲freemonad-logger軟件包不會爲每個其他變壓器提供實例。

+0

「如果缺少實例,那麼你需要用手寫下它們」我知道。我在問「哪個?」如何?」 –