微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决在链的末尾惯用地返回一个 Maybe

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

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,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,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,您可以使用 runMaybeTMaybeT m a 转换为 m (Maybe a)

import Control.Monad.Trans.Maybe(runMaybeT)

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?