删除fromJust的用法

时间:2017-02-22 16:13:22

标签: haskell refactoring maybe

说,我有一些像这样的代码:

data Record = Record {
  validate :: Maybe Bool,
  mobile :: Text
}

someFunction :: Monad m => m ()
someFunction = do
  (record :: Maybe Record) <- getRecord
  let hasValidated = join $ validate <$> record
  case hasValidated of
     Just True -> do
        sendSMS (mobile $ fromJust record)
     _ -> return ()

现在,当hasValidate的值为Just _时,我可以肯定地知道 record不是Nothing。有没有办法删除fromJust 不使用多个案例或不更改签名 sendSMS功能。

请注意,上面的代码是我的简单方案 代码库。

4 个答案:

答案 0 :(得分:5)

我想这对你真正的代码库来说不会令人满意,但是

怎么样
  (record :: Maybe Record) <- getRecord
  case record of
     Just (Record { validate = Just True, mobile = m }) -> do
        sendSMS m
     _ -> return ()

答案 1 :(得分:2)

您可以将布尔值赋予guard

someFunction = do
    mrecord <- getRecord
    let hasValidated = mrecord >>= validate
    case hasValidated >>= guard >> mrecord of
        Just record -> do
            sendSMS (mobile record)
        _ -> return ()

这是一个整洁的解决方案,尽管Daniel Wagner指出它至少执行了一次冗余检查(如果我们将其与Reid Barton's answer进行比较,则检查两次)。只是为了好玩,这是Daniel Wagner's first solution的高尔夫版本:

someFunction = do
    mrecord <- getRecord
    case mrecord >>= liftA2 fmap (,) validate of
        Just (record, True) -> do
            sendSMS (mobile record)
        _ -> return ()

答案 2 :(得分:2)

让您的验证返回它是否有效以及记录的值:

someFunction = do
  mrecord <- getRecord
  let hasValidated = do
        record <- mrecord
        valid <- validated record
        return (valid, record)
  case hasValidated of
     Just (True, record) -> do
        sendSMS (mobile record)
     _ -> return ()

一旦你做出了这个改变,你就可以重构一下:

someFunction = do
  mrecord <- getRecord
  traverse_ (sendSMS . mobile) $ do
    record <- mrecord
    True <- validated record
    return record

答案 3 :(得分:0)

为什么不进行验证

validate :: Monad m => Record -> MaybeT m Record
getRecord :: Monad m => MaybeT m Record

someFunction = fromMaybe () <$> runMaybeT (getRecord >>= validate >>= doStuff)

使验证在验证时返回记录,或在无效时返回Nothing