haskell - 习惯性地在链的末尾返回一个 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 的正确方法是什么,这样如果缺少任何值,那么什么都不会立即返回?
编辑:我的尝试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 转换器:transformers
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 a
为m (Maybe a)
:
import Control.Monad.Trans.Maybe(runMaybeT)
lanchTask :: DeviceRepo m => TaskSpec -> m (Maybe Task)
launchTask = runMaybeT . lanchTask'
推荐阅读
- javascript - 使用 jQuery 在页面加载时将文本复制到输入字段
- reactjs - Bootstrap 列未按预期工作
- c# - Xero API - 多张发票和信用票据的单次付款
- maven - 如何将lib目录中的所有jar文件编译为openjdk9的maven pom.xml
- testing - 无法使用 jest 测试框架测试 LWC 内部的 setter/getter 方法
- microsoft-cognitive - LUIS API 调用“示例话语 - 查看标记示例”返回 404,但通过 API 测试控制台调用时返回 401
- python - python 在 matlab 中是否有相应的 digits() 和 vpa() 函数?
- gitlab - 如果在赛普拉斯 docker 容器中运行,赛普拉斯会中止 XHR 请求
- elasticsearch - Logstash 中的日志未正确解析
- angular - 如何在 Angular 中使用 aria 扩展属性作为侧边栏?