Monad Transformer和Applicative Maybe

时间:2017-04-14 09:13:01

标签: haskell monads monad-transformers 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,但我真的不愿意。

1 个答案:

答案 0 :(得分:2)

编辑:糟糕,修复了一个错误。

您的问题似乎存在轻微的不一致,因为您提供的do-block包含的m a表达式与错误消息中给出的表达式不匹配。

但是,问题最终是这样的:对于某些monad m,在x <- y类型的do-block中,每个简单表达式(以及m b表达式的每个右侧)某些b必须包含runReaderT ...类型。因此,通过在ExceptT String IO ()类型的do-block中使用ExceptT String IO a表达式,您强制Haskell对某些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 表达式适应周围的do-block。两个合理的选择是:

ExceptT
如果您的maybeReaderNothing或<:p>,

会引发foo = do ... maybe (return ()) liftIO $ runReaderT ... undefined 式错误

Nothing

这将... {erm .. $.ajax({ type:'GET', url:"https://api.xxxxxxxxxxx/v1/" +code+ "?api_key="+API_KEY, data:{_token: "{{ csrf_token() }}", }, success: function( msg ) { } }); 的情况。

相关问题