如何解决在链的末尾惯用地返回一个 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
,您可以使用 runMaybeT
将 MaybeT m a
转换为 m (Maybe a)
:
import Control.Monad.Trans.Maybe(runMaybeT)
lanchTask :: DeviceRepo m => TaskSpec -> m (Maybe Task)
launchTask = runMaybeT . lanchTask'
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。