如何使用 bind 和 fmap 编写此代码?



如何使用bind&如何编写函数事务而无需通知。FMAP?

    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

我的尝试是沿着这些行:

    transaction :: UTCTime -> EncUser -> STM (Either Text ())
    transaction now user = do
      readTVar db
      >>= return . isValidRequest
      >>= fmap (confirmRegistration user)
      where isValidRequest = registrationExists >=> isConfirmationValid now

...但是汇编失败了,错误的bellow失败了,我似乎不明白如何在Isvalidrequest产生的任何一个结果上进行fmap确认注册

• Couldn't match type ‘Either Text’ with ‘STM’
  Expected type: Either Text Registration -> STM (Either Text ())
    Actual type: STM Registration -> STM (Either Text ())
• In the second argument of ‘(>>=)’, namely
    ‘fmap (confirmRegistration user)’
  In the expression:
    do { readTVar db } >>= return . isValidRequest
    >>= fmap (confirmRegistration user)
  In an equation for ‘transaction’:
      transaction now user
        = do { readTVar db } >>= return . isValidRequest
          >>= fmap (confirmRegistration user)
        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

这是我修复了梅尔托内(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

注意:操作员&lt;>是此处找到的"函数组合"

我仍然缺少直觉,为什么在那里需要 sequence ,但我可能应该将其发布为另一个问题。

最新更新