2017-04-14 2 views
1

そのよう:モナド変圧器および応用的かもしれない

let maybeReader :: Maybe (ReaderT UDCEnv IO()) = 
    uploadVersionFilesToCaches s3BucketName <$> maybeFilePath <*> Just gitRepoNamesAndVersions 

私はそうであっても同じようReaderTを実行することができます。

let maybeIO :: Maybe (IO()) = 
    runReaderT <$> maybeReader <*> Just (env, shouldIgnoreLocalCache, verbose) 

let式を使用している限り、すべて正常に動作します。

f :: ... -> ExceptT String IO() 
f ... = do 
    ... 
    runReaderT <$> maybeReader <*> Just (env, shouldIgnoreLocalCache, verbose) -- Error here 
    undefined 

を生成します:できるだけ早く私は実際に上記の式で letをドロップするように私は省略しています ExceptT String IO FilePath代わりの Maybe

部分は...でマークされているようにApplicativeを評価された式は、型を取得していしよう

Couldn't match type ‘IO()’ with ‘()’ 
Expected type: ReaderT UDCEnv IO() -> UDCEnv ->() 
    Actual type: ReaderT UDCEnv IO() -> UDCEnv -> IO() 
In the first argument of ‘(<$>)’, namely ‘runReaderT’ 
In the first argument of ‘(<*>)’, namely 
    ‘runReaderT 
    <$> 
    (uploadVersionFilesToCaches s3BucketName <$> maybeFilePath 
     <*> Just gitRepoNamesAndVersions)’ 
/Users/blender/Code/Personal/Haskell/Rome-Public/src/Lib.hs: 82, 73 

Couldn't match type ‘Maybe’ with ‘ExceptT String IO’ 
    Expected type: ExceptT String IO FilePath 
     Actual type: Maybe FilePath 
    In the second argument of ‘(<$>)’, namely ‘maybeFilePath’ 
    In the first argument of ‘(<*>)’, namely 
     ‘uploadVersionFilesToCaches s3BucketName <$> maybeFilePath’ 

最初のエラーはどこかでliftIOが不足していると思います。

しかし、私は誤解されたApplicativeについて何をすべきか分かりません。

Applicativeを使用する代わりに、おそらくMaybeを分析することができましたが、私は本当にそうしたくありません。

+0

エラーから判断すると、「liftIO」ではなく「return」がありません。 – arrowd

+0

@arrowdはうまくいくかもしれませんが、残念なことにここで私の適用上の問題に役立ちません。たぶん、これは正しいアプローチではないでしょうか? – tmpz

+0

'runReaderT ...'式が実際に現れるコードを含めることができますか?おそらく、それは、Haskellが 'Maybe(IO)()'の代わりに 'ExceptT String IO()'とタイプしようとしているようなdo-blockで使われている可能性が高いです。 'Maybe'は' ExceptT String IO'ではなく、 '()'は 'IO()'ではないので、これは最終的に両方のエラーを説明します。これは、標準Maybe-to-ExceptTインターフェイスを追加するのと同じくらい簡単かもしれません。 –

答えて

2

編集:ありがとうございました。

あなたが提供するdo-blockにエラーメッセージに示されている式と一致しないrunReaderT ...という式が含まれているため、ご質問に多少の矛盾があるようです。

しかし、最終的には問題は、このです:いくつかのモナドmの型m aのDOブロックで、各普通発現(及びx <- y式の各右辺)が、いくつかのbの型m bを有していなければなりません。だからExceptT String IO()タイプのdoブロックでrunReaderT ...式を使用すると、HaskellはそれをあるタイプのExceptT String IO aa)としてタイプチェックすることになります。ただし、Maybe (IO())なので、型チェックは失敗します。

あなたがしようとした場合は、同様のエラーを取得したい:

foo :: ExceptT String IO() 
foo = do Just (putStrLn "won't work") -- has type Maybe (IO()) 
     undefined 

をあなたは周囲のdoブロックへrunReaderT ...式を適応する方法を決定する必要があります。二つの合理的なオプションは次のとおりです。あなたのmaybeReaderがある場合ExceptTスタイルのエラーがスローされます

foo = do ... 
     maybe (throwError "reader was Nothing!") liftIO 
      $ runReaderT ... 
     undefined 

Nothingか.. ERM .. Nothingの場合は何もしません

foo = do ... 
     maybe (return()) liftIO 
      $ runReaderT ... 
     undefined 

+0

編集してください。そうです、私はエラーメッセージとそれらの' T'全てを完全に混乱させました。一般的に私はモナド変圧器を構成することは非常に難しいと思う、 'maybe'(wink wink)私はそれを間違っている:) – tmpz

関連する問題