Haskell 如何使用bind&;编写此代码;fmap?

Haskell 如何使用bind&;编写此代码;fmap?,haskell,Haskell,如何使用bind和fmap编写没有do符号的函数事务 transaction :: UTCTime -> EncUser -> STM (Either Text ()) transaction now user = do dbData <- readTVar db case isValidRequest dbData of Right _ -> do confirmRegistration user

如何使用bind和fmap编写没有do符号的函数事务

    transaction :: UTCTime -> EncUser -> STM (Either Text ())
    transaction now user = do
      dbData <- readTVar db
      case isValidRequest dbData of
        Right _ -> do confirmRegistration user
                      return $ Right ()
        Left err -> return $ Left err
      where isValidRequest = registrationExists >=> isConfirmationValid now

    confirmRegistration :: EncUser -> STM () 
    registrationExists :: DbData -> Either Text Registration
    isConfirmationValid :: UTCTime -> Registration -> Either Text Registration
…但编译失败,出现下面的错误,我似乎不明白如何在isValidRequest生成的两个结果之上fmap confirmRegistration


do
符号相当机械:

transaction now user =
  readTVar db >>= \dbData ->
  case isValidRequest dbData of
    Right _ -> confirmRegistration user >>
               return (Right ())
    Left err -> return $ Left err
  where isValidRequest = registrationExists >=> isConfirmationValid now

do
符号相当机械:

transaction now user =
  readTVar db >>= \dbData ->
  case isValidRequest dbData of
    Right _ -> confirmRegistration user >>
               return (Right ())
    Left err -> return $ Left err
  where isValidRequest = registrationExists >=> isConfirmationValid now

这是在我修改了confirmRegistration的类型之后,在melpomene的注释之后的最终代码。我将此作为参考发布,因为它看起来非常接近我最初想要的东西

transaction :: UTCTime -> Text -> EncUser -> STM (Either Text ())
transaction now rid user = do
  readTVar db
  >>= sequence . confirmRegistration user <.> isValidRequest
  where isValidRequest = findRegistration rid >=> isConfirmationValid now

confirmRegistration :: EncUser -> Registration -> STM ()
findRegistration :: Text -> DbData -> Either Text Registration
isConfirmationValid :: UTCTime -> Registration -> Either Text Registration
transaction::UTCTime->Text->EncUser->STM(任意文本())
事务现在rid user=do
readTVar数据库
>>=序列。确认注册用户isValidRequest
其中isValidRequest=findRegistration rid>=>现在确认有效吗
confirmRegistration::EncUser->Registration->STM()
findRegistration::Text->DbData->任一文本注册
isConfirmationValid::UTCTime->注册->任一文本注册
注:运算符为“函子合成”


不过我还是不明白为什么这里需要序列,但我可能应该把它作为一个不同的问题发布

这是在我修改了confirmRegistration的类型之后,在melpomene的注释之后的最终代码。我将此作为参考发布,因为它看起来非常接近我最初想要的东西

transaction :: UTCTime -> Text -> EncUser -> STM (Either Text ())
transaction now rid user = do
  readTVar db
  >>= sequence . confirmRegistration user <.> isValidRequest
  where isValidRequest = findRegistration rid >=> isConfirmationValid now

confirmRegistration :: EncUser -> Registration -> STM ()
findRegistration :: Text -> DbData -> Either Text Registration
isConfirmationValid :: UTCTime -> Registration -> Either Text Registration
transaction::UTCTime->Text->EncUser->STM(任意文本())
事务现在rid user=do
readTVar数据库
>>=序列。确认注册用户isValidRequest
其中isValidRequest=findRegistration rid>=>现在确认有效吗
confirmRegistration::EncUser->Registration->STM()
findRegistration::Text->DbData->任一文本注册
isConfirmationValid::UTCTime->注册->任一文本注册
注:运算符为“函子合成”


不过我还是不明白为什么这里需要序列,但我可能应该把它作为一个不同的问题发布

上述表达式的情况非常类似于任何一个的fmap实现,因此这就是为什么我想使用fmap来代替它-of@vidi您不能,因为您有
confirmRegistration user>
。没有它,您可以像这样提取
return
return(case isValidRequest dbData of Right->Right();Left err->Left err)
,这就是
返回(fmap(const())(isValidRequest dbData))
。但那不是你所拥有的。现在我意识到这里的确认注册类型是错误的。我会修好类型,然后回来。谢谢同时,您是对的,鉴于原始问题中的类型,上述表达式的大小写与其中一个的fmap实现非常相似,因此这就是为什么我希望使用fmap来代替大小写-of@vidi您不能,因为您有
confirmRegistration user>
。没有它,您可以像这样提取
return
return(case isValidRequest dbData of Right->Right();Left err->Left err)
,这就是
返回(fmap(const())(isValidRequest dbData))
。但那不是你所拥有的。现在我意识到这里的确认注册类型是错误的。我会修好类型,然后回来。谢谢同时,考虑到原始问题中的类型,你是对的