[英]Monad Transformer and applicative Maybe
Inside a do block of a ExceptT String IO ()
在
ExceptT String IO ()
的do块内
I have a function that produces a ReaderT like so: 我有一个生成ReaderT的函数,如下所示:
type UDCEnv = (AWS.Env, Bool)
uploadVersionFilesToCaches :: S3.BucketName
-> FilePath
-> [GitRepoNameAndVersion]
-> ReaderT UDCEnv IO ()
I just so happen to have a Maybe FilePath
so I create my ReaderT like so: 我碰巧有一个
Maybe FilePath
所以我这样创建了ReaderT:
let maybeReader :: Maybe (ReaderT UDCEnv IO ()) =
uploadVersionFilesToCaches s3BucketName <$> maybeFilePath <*> Just gitRepoNamesAndVersions
I can even run the ReaderT like so: 我什至可以像这样运行ReaderT:
let maybeIO :: Maybe (IO ()) =
runReaderT <$> maybeReader <*> Just (env, shouldIgnoreLocalCache, verbose)
Everything works fine as long as I use let
expressions. 只要我使用
let
表达式,一切都可以正常工作。 As soon as I drop the let
in the expression above to actually try to have expression evaluated Applicative gets types as ExceptT String IO FilePath
instead of Maybe
我在上面的表达式中放下
let
以实际尝试对表达式求值后,Applicative将类型作为ExceptT String IO FilePath
而不是Maybe
The parts I am omitting are marked by ...
: 我省略的部分以
...
标记:
f :: ... -> ExceptT String IO ()
f ... = do
...
runReaderT <$> maybeReader <*> Just (env, shouldIgnoreLocalCache, verbose) -- Error here
undefined
Produces 产生
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’
I think the first error is because I'm missing some liftIO
somewhere. 我认为第一个错误是因为我在某处缺少了一些
liftIO
。
However I have no idea what to do about the misunderstood Applicative. 但是,我不知道该如何处理被误解的应用程序。
I could case analysis on the Maybe of course instead of using Applicative but I would really prefer not to. 当然,我可以对Maybe进行案例分析,而不是使用Applicative,但我真的不愿意。
Edit: Oops, fixed a bug. 编辑:糟糕,修正了一个错误。
There seems to be a minor inconsistency in your question, because the do-block you provide contains a runReaderT ...
expression that doesn't match the expression given in your error message. 您的问题似乎存在一些细微的矛盾,因为您提供的do-block包含一个
runReaderT ...
表达式,该表达式与错误消息中给出的表达式不匹配。
However, ultimately the problem is this: in a do-block of type ma
for some monad m
, each plain expression (and each right-hand side of an x <- y
expression) has to have type mb
for some b
. 但是,最终的问题是这样的:对于某些monad
m
,在ma
类型的do块中,每个简单表达式(以及x <- y
表达式的每个右侧)必须对于某些b
具有mb
类型。 So, by using your runReaderT ...
expression in a do-block of type ExceptT String IO ()
, you're forcing Haskell to type-check it as ExceptT String IO a
for some a
. 因此,通过使用您
runReaderT ...
表达类型的DO-块ExceptT String IO ()
你这是在强迫Haskell的类型检查它作为ExceptT String IO a
对一些a
。 However, it's a Maybe (IO ())
, so that type-checking will fail. 但是,它是
Maybe (IO ())
,因此类型检查将失败。
You'd get a similar error if you tried: 如果您尝试以下操作,则会收到类似的错误:
foo :: ExceptT String IO ()
foo = do Just (putStrLn "won't work") -- has type Maybe (IO ())
undefined
You need to decide how to adapt the runReaderT ...
expression to the surrounding do-block. 您需要确定如何使
runReaderT ...
表达式适应周围的do-block。 Two reasonable options are: 两种合理的选择是:
foo = do ...
maybe (throwError "reader was Nothing!") liftIO
$ runReaderT ...
undefined
which will throw an ExceptT
-style error if your maybeReader
is Nothing
or: 如果您的
maybeReader
为Nothing
,则将抛出ExceptT
风格的错误或:
foo = do ...
maybe (return ()) liftIO
$ runReaderT ...
undefined
which will do .. erm .. nothing in case of Nothing
. 万一
Nothing
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.