2017-11-30 9 views
1

logging-errorpipesで処理しようとしています。私は何かが働いているという意味ではほぼそこにいますが、それは正しいとは思えず、それを修正する方法がわかりません。コード:私はそれ以外の場合はコンパイルされませんliftlogInfoに必要readInputMessageパイプでMonadLogを使用するときに持ち上げる必要がある理由

{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE NoImplicitPrelude #-} 
{-# LANGUAGE PartialTypeSignatures #-} 

module Main where 

import   Protolude hiding ((<>), empty, for, get) 

import   Control.Monad.Log 
import   Text.PrettyPrint.Leijen.Text 

import   Pipes 


testApp :: (MonadIO m, MonadLog (WithSeverity Doc) m) => m() 
testApp = logInfo $ textStrict "Logging works. Yah!" 


printMessage :: (MonadIO m, MonadLog (WithSeverity Doc) m) => Consumer Text m() 
printMessage = forever $ await >>= putStrLn 


readInputMessage :: (MonadIO m, MonadLog (WithSeverity Doc) m) => Producer Text m() 
readInputMessage = forever action  
    where 
    action = do 
     liftIO $ putStr ("> " :: Text) 
     liftIO getLine >>= yield 
     lift $ logInfo $ text "Waits with abated breath" 


runMyLogging :: MonadIO m => LoggingT (WithSeverity Doc) m a -> m a 
runMyLogging f = runLoggingT f (print . renderWithSeverity identity) 


runPipesApp :: IO() 
runPipesApp = runMyLogging $ runEffect $ 
     readInputMessage 
    >-> printMessage 


runTestApp :: IO() 
runTestApp = runMyLogging testApp 


main :: IO() 
main = do 
    runTestApp 
    runPipesApp 

。しかし、testApplogInfoは持ち上げる必要がありません。なぜ私は持ち上げる必要がありますが、もう一方は持ち上げる必要はありませんか?

liftがなければ、これはコンパイルエラーです:

/home/rgh/dev/haskell/fa-logging/app/Main.hs:29:7: error: 
    • Could not deduce (MonadLog 
          (WithSeverity Doc) (Pipes.Proxy X()() Text m)) 
     arising from a use of ‘logInfo’ 
     from the context: (MonadIO m, MonadLog (WithSeverity Doc) m) 
     bound by the type signature for: 
        readInputMessage :: forall (m :: * -> *). 
             (MonadIO m, MonadLog (WithSeverity Doc) m) => 
             Producer Text m() 
     at app/Main.hs:23:1-84 
    • In a stmt of a 'do' block: 
     logInfo $ text "Waits with abated breath" 
     In the expression: 
     do liftIO $ putStr ("> " :: Text) 
      liftIO getLine >>= yield 
      logInfo $ text "Waits with abated breath" 
     In an equation for ‘action’: 
      action 
      = do liftIO $ putStr ("> " :: Text) 
       liftIO getLine >>= yield 
       logInfo $ text "Waits with abated breath" 
    | 
29 |  logInfo $ text "Waits with abated breath" 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

-- While building package fa-logging-0.0.0 using: 
     /srv/cache/rgh/.stack/setup-exe-cache/x86_64-linux-nopie/Cabal-simple_mPHDZzAJ_2.0.0.2_ghc-8.2.1 --builddir=.stack-work/dist/x86_64-linux-nopie/Cabal-2.0.0.2 build lib:fa-logging exe:fa-logging --ghc-options " -ddump-hi -ddump-to-file" 
    Process exited with code: ExitFailure 1 

私はコンパイラがあるが、私はそれを修正する方法がわからないどのようなタイプmうまくできないため、はそれがコンパイルしないと思う

答えて

1

pipesのタイプがMonadLogのインスタンスではないという問題があります。 testAppでは、だから我々はMonadLogのインスタンスである

(MonadLog (WithSeverity Doc) m) => m() 

を宣言しました。比較的、readInputMessageのために、あなたはとても種類mMonadLogのインスタンスですが、私たちはでタイプm()じゃない

(MonadLog (WithSeverity Doc) m) => Producer Text m() 

を宣言しました。我々はタイプProducer Text m()です。 liftを使用すると、私たちはmのモナドになります。これはあなたが観察したものです。

解決策は、内部モナドのときにMonadLogというパイプタイプメンバーを作成することです。あなたが孤立したインスタンスを用意したい場合は、以下のようなコードを書くことができます。

instance (MonadLog m) => MonadLog Proxy a' a b' b m r where 
    askLogger = lift askLogger 
    localLogger f = lift . localLogger x 

この

あなたがいる限り、内部モナドも MonadLogあるとしてパイプタイプのいずれかで MonadLogを使用できるようにする必要があります。

+1

しかし、孤児のインスタンスは悪です。手動で持ち上げるほうがいいですか? – dfeuer

+0

@dfeuer私はそれについても幸せではない。本当に必要なことは、Snoymanが上記のコードでインスタンス(MonadLogger m、MonadTrans t)=> MonadLogger(t m)を追加する必要があることです。 MonadLoggerはすでにMtlに依存しており、ProxyはすでにMonadTransであるため、他のすべては世話をします。それが起こるまで、しかし、彼らは邪悪な孤児のインスタンスに対処しなければならないか、彼らが特に避けるために質問したリフトをつける必要があります。 – user640078

+0

MonadLoggerのコードをもう一度見れば、MonadTransのオプションがいくつかあるようですが、どうやらもっと良い答えがあるのだろうかと思います。 – user640078

関連する問題