如何用bind&编写这段代码FMAP?

时间:2017-02-23 09:08:35

标签: haskell

如何在不使用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

...但编译失败,错误如下,我似乎无法理解如何在isValidRequest生成的任一结果之上fmap confirmRegistration

• 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 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

   #####Get Registry Value #### 
$main = "LocalMachine"
$path= "registry key path"
$servers = Get-Content c:\input.txt #-- Get all the servers
$arr=New-Object System.Collections.ArrayList

foreach ($Server in $servers)  
{ 

$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($main, $Server) 
$regKey= $reg.OpenSubKey($path) 
$Value = $regkey.GetValue($key) 
$arr.Add($Value)
}
$arr

注意:运营商&lt;。&gt;是“functor composition”找到here

我仍然缺少直觉,为什么序列需要,但我应该将其作为一个不同的问题发布。