Haskell: Turtle: 如何从Shell中获取返回值

5

如何从Shell monad中提取值?

我想像bash的&&一样排序一个命令列表,但我也想提取最终的ExitCode值。

假设我有以下代码:

import           Turtle

type Commands = [Shell ExitCode]
run :: (MonadIO io) => Commands -> io ExitCode
run cs = whatIsThisFunction $ Prelude.foldl (.&&.) (return ExitSuccess) cs

whatIsThisFunction :: (MonadIO io) => Shell a -> io a
whatIsThisFunction = undefined

我试图使用Control.Foldl实现这个功能,但没有找到解决方案。

有什么想法吗?

更普遍地说,为什么Turtle不提供一个具有这样签名的函数:

sh' :: MonadIO io => Shell a -> io a 
2个回答

5

Turtle.Shell 为您提供了一个 fold :: MonadIO io => Shell a -> Fold a b -> io b,而 Control.Foldl 则提供了一组 Fold,其中包括: last :: Fold a (Maybe a)。您可以将两者组合在一起来提取命令返回的最后一个 ExitCode,就像这样:

import Control.Monad.IO.Class
import Turtle.Shell  as TS
import Control.Foldl as CF

sh' :: MonadIO io => Shell a -> io (Maybe a)
sh' c = TS.fold c CF.last

谢谢!我一直在寻找这样的东西! - damien.courousse
顺便说一句,在Turtle中处理错误的更惯用方式似乎是使用异常。那么代码看起来会更像:Tt.sh cmds `catches` [ Handler (\(e::Tt.ProcFailed) -> Log.error $ show e) , Handler (\(e::Tt.ShellFailed) -> Log.error $ show e) , -- etc. ] 你同意吗?(抱歉代码格式不好,我不知道如何在评论中处理) - damien.courousse

3

sh' :: MonadIO io => Shell a -> io a 不可能实现,因为 Shell a 可能由 [a] 构造而成(由 select :: [a] -> Shell a 证明),而该列表可能为空。


1
使用 IO,你可以让它直接抛出异常。更好的解决方案是将其改为 io (Maybe a) - Reactormonk
所以,当我的回答被踩的时候,是因为它太短了还是因为它包含错误的信息?我没有详细说明要做什么,因为提问者已经表明他们知道Control.Foldl。因此,对我来说,问题只是为什么那个特定的签名不是库的一部分。@Reactormonk建议我的“不可能”的措辞可能过于强硬。我的异常意见与我的undefined意见并没有太大不同。 - erisco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接