我有以下代码:
foldM (\exitCode args -> pure exitCode .&&. someCmdWith args) ExitSuccess argss
有没有更好的抽象我可以用来应用于 apply to.&&.
的结果?someCmdWith
argss
我有以下代码:
foldM (\exitCode args -> pure exitCode .&&. someCmdWith args) ExitSuccess argss
有没有更好的抽象我可以用来应用于 apply to.&&.
的结果?someCmdWith
argss
这行得通吗?
runCmds argss = foldr (.&&.) (pure ExitSuccess) (fmap someCmdWith argss)
如果您想写得更短,我相信这也可以:
runCmds = foldr (.&&.) (pure ExitSuccess) . fmap someCmdWith
(.&&.)
看起来是关联的,似乎有一个中性元素 ( pure ExitSuccess
) 所以让我们定义一个Monoid
:
newtype UntilFailure = UntilFailure { runUntilFailure :: IO ExitCode }
instance Monoid UntilFailure where
mappend (UntilFailure a1) (UntilFailure a2) = UntilfFailure (a1 .&&. a2)
mempty = UntilFailure (pure ExitSuccess)
然后我们可以写如下内容:
runUntilFailure . foldMap UntilFailure $ someCmdWith <$> argss
定义 a 的好处Monoid
是,每次折叠项目列表时,我们不必记住哪个是中性元素,因为它是“在类型中烘焙的”,可以这么说。
但是,我认为不能定义一个幺半群(.||.)
,因为中性元素必须以某种方式保留前一个命令的退出代码。不过,仍然可以定义 a Semigroup
。