2017-11-30 3 views
1

으로 작업하는 logging-error을 얻으려고합니다. 나는 거의 작동하고 있다는 의미에서 그렇습니다. 그러나 나는 그것이 옳다고 생각하지 않으며 그것을 고치는 방법을 모른다. 코드 : readInputMessage에서MonadLog with pipe를 사용할 때 왜 들어야합니까?

{-# 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 

나는 그렇지 않으면 컴파일되지 않습니다 liftlogInfo해야합니다. 그러나 testApplogInfo은 리프트 할 필요가 없습니다. 왜 내가 들어올 필요가 있습니까?

/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이 어떤 종류의 운동을 할 수는 없지만 나는 그것을 해결하는 방법을 모르기 때문에이 컴파일 아니에요 생각 : lift이없이

은 컴파일 오류입니다.

답변

1

pipes의 형식이 MonadLog이 아닌 것이 문제입니다. testApp에서는

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

그래서 우리는 MonadLog의 인스턴스에 선언했습니다. 비교적, readInputMessage를 들어,
(MonadLog (WithSeverity Doc) m) => Producer Text m() 

그래서 유형 mMonadLog의 인스턴스

을 선언했지만, 우리는하지 에서 유형 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

관련 문제