2017-02-23 4 views
0

バインド& fmapを使用して、do-notationなしでファンクショントランザクションをどのように書くことができますか?このコードを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 

...しかし、コンパイルはエラー怒鳴るで失敗し、私はどちらかの結果の上にconfirmRegistrationを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 

答えて

2

do N isValidRequestによって産生さotationはかなりの機械です:

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 
+0

上記のcase-of式はどちらかのfmap実装と非常によく似ていますので、代わりにfmapを使用したいのですが – vidi

+0

@vidiあなたは 'confirmRegistration user >>'を持っているのでできません。それがなければ 'return(fmap(const()(isValidRequest dbData)')というreturn(これは右の_ - > Right();左エラー - >左エラー) ) '。しかし、それはあなたが持っているものではありません。 – melpomene

+0

ここでconfirmRegistrationのタイプが間違っていることに気付きました。タイプを修正して戻ってきます。ありがとう。一方で、あなたは正しいです、元の質問の種類 – vidi

0

私はメルポメネからのコメント後、confirmRegistrationの型を固定した後、これが最終的なコードです。私は参照としてこれを投稿しています。なぜなら、最初に欲しかったものに非常に近いからです。

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 

注:オペレータ<>「ファンクタ組成物」here

はまだ私はそこに必要なシーケンスがあるが、私はおそらく別の質問としてあることを投稿しなければならない理由を直感欠けている発見されました。

関連する問題