如何使用綁定& 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
...但編譯失敗,錯誤波紋管,我似乎無法理解如何FMAP confirmRegistration上無論結果的頂部通過isValidRequest
• 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
上面的case-of表達式與Either的fmap實現非常相似,所以這就是爲什麼我想用fmap代替case的 – vidi
@vidi你不能,因爲你有'confirmRegistration user >>'在那裏。沒有它,你可以像這樣提取'return':return(fmap(const())(isValidRequest dbData)返回(case isValidRequest dbData Right_-> Right(); Left err-> Left err) )'。但那不是你所擁有的。 – melpomene
現在我意識到confirmRegistration的類型在這裏是錯誤的。我會修復類型並回來。謝謝。與此同時,你是對的,給出原始問題中的類型 – vidi