Monad Transformer 和应用程序 Maybe
Monad Transformer and applicative Maybe
在 ExceptT String IO ()
的 do 块内
我有一个生成 ReaderT 的函数,如下所示:
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
放在上面的表达式中以实际尝试对表达式求值,Applicative 就会将类型获取为 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
。
但是我不知道如何处理被误解的 Applicative。
我当然可以在 Maybe 上进行案例分析,而不是使用 Applicative,但我真的不想这样做。
编辑:糟糕,修复了一个错误。
您的问题似乎有一点不一致,因为您提供的 do-block 包含一个 runReaderT ...
表达式,与您在错误消息中给出的表达式不匹配。
然而,最终的问题是:在一个 m a
类型的 do-block 中,对于一些 monad m
,每个普通表达式(以及 x <- y
表达式) 对于某些 b
必须具有类型 m 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 ...
表达式适应周围的 do 块。两个合理的选择是:
foo = do ...
maybe (throwError "reader was Nothing!") liftIO
$ runReaderT ...
undefined
如果您的 maybeReader
是 Nothing
或:
,这将引发 ExceptT
式的错误
foo = do ...
maybe (return ()) liftIO
$ runReaderT ...
undefined
在 Nothing
的情况下,这将执行 .. 呃 .. 什么也做不了。
在 ExceptT String IO ()
我有一个生成 ReaderT 的函数,如下所示:
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
放在上面的表达式中以实际尝试对表达式求值,Applicative 就会将类型获取为 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
。
但是我不知道如何处理被误解的 Applicative。
我当然可以在 Maybe 上进行案例分析,而不是使用 Applicative,但我真的不想这样做。
编辑:糟糕,修复了一个错误。
您的问题似乎有一点不一致,因为您提供的 do-block 包含一个 runReaderT ...
表达式,与您在错误消息中给出的表达式不匹配。
然而,最终的问题是:在一个 m a
类型的 do-block 中,对于一些 monad m
,每个普通表达式(以及 x <- y
表达式) 对于某些 b
必须具有类型 m 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 ...
表达式适应周围的 do 块。两个合理的选择是:
foo = do ...
maybe (throwError "reader was Nothing!") liftIO
$ runReaderT ...
undefined
如果您的 maybeReader
是 Nothing
或:
ExceptT
式的错误
foo = do ...
maybe (return ()) liftIO
$ runReaderT ...
undefined
在 Nothing
的情况下,这将执行 .. 呃 .. 什么也做不了。