2017-04-14 39 views
1

內部的ExceptT String IO()單子轉換和應用性也許

我有一個產生ReaderT像這樣一個功能的DO塊:

type UDCEnv = (AWS.Env, Bool) 

uploadVersionFilesToCaches :: S3.BucketName 
           -> FilePath 
           -> [GitRepoNameAndVersion] 
           -> ReaderT UDCEnv IO() 

我只是這麼碰巧有一個Maybe FilePath所以我創造我ReaderT像這樣:

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

我甚至可以運行ReaderT像這樣:

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

只要我使用let表達式,一切正常。當我在表達降let上述實際嘗試有表達式計算應用型變類型爲ExceptT String IO FilePath而不是Maybe

我忽略被標記的部分由...

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

主要生產

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

但是我不知道如何處理誤解的應用程序。

我可以對Maybe的案例分析,而不是使用Applicative,但我真的不想使用Applicative。

+0

從錯誤判斷,您缺少'return',而不是'liftIO'。 – arrowd

+0

@arrowd很可能,但不幸的是,這對我的應用問題沒有幫助。也許這不是正確的做法? – tmpz

+0

您可以在runreaderT ...表達式實際出現的地方包含代碼嗎?最有可能的是,它被用在do-block中,Haskell試圖將它輸入爲「ExceptT String IO()」而不是'Maybe(IO())'。這最終會解釋這兩個錯誤,因爲'Maybe'不是'ExceptT String IO',而'()'不是'IO()'。這可能與添加標準的Maybe-to-ExceptT接口一樣簡單。 –

回答

2

編輯:糟糕,修正了一個錯誤。

您的問題似乎有一點不一致,因爲您提供的do-block包含一個runReaderT ...表達式,它與您的錯誤消息中給出的表達式不匹配。

然而,最終的問題是這樣的:在m a類型的DO-塊一些單子m,各平表達(和x <- y表達式的每個右側)必須具有類型m b一些b。因此,通過在ExceptT String IO()類型的do塊中使用您的runReaderT ...表達式,您需要強制Haskell將其鍵入爲ExceptT String IO a(對於某些a)。但是,這是一個Maybe (IO()),因此類型檢查將失敗。

你會得到一個類似的錯誤,如果你嘗試過:

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

您需要決定如何適應runReaderT ...表達對周圍做塊。兩個合理的選項是:

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

如果您maybeReader是會拋出ExceptT式的錯誤Nothing或:

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

這將做..呃..沒有在Nothing情況。

+0

你是對的,我完全被錯誤信息和所有'T'所困惑。一般來說,我發現編寫單聲道變壓器非常困難,'也許'(眨眼眨眼)我做錯了:) – tmpz