haskell - 在链的末尾惯用地返回一个 Maybe

标签 haskell monads monad-transformers

这个问题在这里已经有了答案:





How do I deal with many levels of indentation?

(3 个回答)


11 个月前关闭。




我有以下代码片段,它有点工作:

launchTask :: (DeviceRepo m) => TaskSpec -> m (Maybe Task)
launchTask taskSpec@TaskSpec { taskSpecImage = image
                             , taskSpecRequirement = requirement
                             } = do
  mayDevice <- getDeviceMatchingRequirement requirement
  case mayDevice of
    Nothing -> return Nothing
    Just device -> do
      mayContainer <- createContainer device requirement
      case mayContainer of
        Nothing -> return Nothing
        Just container ->
          return $
          Just
            Task
              { taskName = pack image
              , taskStatus = TaskStatusRunning
              , taskSpec = taskSpec
              , taskContainerId = containerId container
              }

不过,我觉得这不是很地道。什么是堆叠主要计算(来自 DeviceRepo m)以及可能的 Maybe monad 的正确方法,以便如果缺少任何值,则立即返回 Nothing ?
编辑 : 我对 MaybeT 的尝试, 但类型不匹配
launchTask2 :: (DeviceRepo m) => TaskSpec -> m (Maybe Task)
launchTask2 taskSpec@TaskSpec { taskSpecImage = image
                              , taskSpecRequirement = requirement
                              } = runMaybeT launcher
  where
    launcher :: MaybeT m Task
    launcher =
      getDeviceMatchingRequirement requirement >>= \device ->
        createContainer device requirement >>= \container ->
          return
            Task
              { taskName = pack image
              , taskStatus = TaskStatusRunning
              , taskSpec = taskSpec
              , taskContainerId = containerId container
              }
    • Couldn't match expected type ‘Device’
                  with actual type ‘Maybe Device’
    • In the first argument of ‘createContainer’, namely ‘device’
      In the first argument of ‘(>>=)’, namely
        ‘createContainer device requirement’
      In the expression:
        createContainer device requirement
          >>=
            \ container
              -> return
                   Task
                     {taskName = pack image, taskStatus = TaskStatusRunning,
                      taskSpec = taskSpec, taskContainerId = containerId container}
   |
58 |         createContainer device requirement >>= \container ->
   |                         ^^^^^^

最佳答案

您可能正在寻找 MaybeT monad transformer来自 transformers package :

import Control.Monad.Trans.Maybe(MaybeT(MaybeT))

launchTask' :: DeviceRepo m => TaskSpec -> MaybeT m Task
launchTask' taskSpec@TaskSpec { taskSpecImage = image, taskSpecRequirement = requirement } = do
    device <- MaybeT (getDeviceMatchingRequirement requirement)
    container <- MaybeT (createContainer device requirement)
    return Task
        { taskName = pack image
        , taskStatus = TaskStatusRunning
        , taskSpec = taskSpec
        , taskContainerId = containerId container
        }
因此这是一个函数 MaybeT m Task ,您可以使用 runMaybeT 改造MaybeT m am (Maybe a) :
import Control.Monad.Trans.Maybe(runMaybeT)

lanchTask :: DeviceRepo m => TaskSpec -> m (Maybe Task)
launchTask = runMaybeT . lanchTask'

关于haskell - 在链的末尾惯用地返回一个 Maybe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65550352/

相关文章:

haskell - 函数的模式匹配

haskell - 与 Arrow 和 Applicative 不同,为什么互让让 ArrowApply 和 Monads 等价?

.net - 状态单子(monad),为什么不是一个元组?

monad-transformers - 用于卤素元件的 Monad 变压器

haskell - 在复合 StateT/Maybe monad 中,如何采取任何一种成功的可能性?

scala - monad 转换器是否适用于从服务获取 JSON?

haskell - 从任意节点列表生成边

haskell - 在 Haskell 中实现函数重载

performance - Repa 3 性能和正确使用 'now'

haskell - Haskell 中的函数是否总是评估其返回值?