Dear Pipers (Pipe Smokers?),
Please accept my apologies for a lengthy example for what is undoubtedly
a simple problem, but I'm struggling to know how best to simplify.
I'm writing a little command-execution package. It's primarily for my
own learning, so don't worry about "couldn't I use package X...".
I have a 'systemx' function, that creates a command that will be run
with stdout/stderr inherited from the process:
systemx :: (MonadError ExecError μ, MonadReader (ProcExecCtxt3 μ) ρ)
=> CmdSpec -> ρ (Producer [CmdSpec] μ ())
A CmdSpec is a command specification - that is, an executable name &
some arguments.
ProcExecCtxt3 holds an 'executor' - a function to 'execute' the command;
in normal circumstances, this uses System.Process et al, but it's
replaceable so that I could
mock the command. Hence the free typevar μ, which is MonadIO in normal
circumstances but could be a non-IO monad for mock purposes. The
ExecError is thrown if the command returns non-zero.
The producer is to "log" the commands run - when mocking, I can use a
MonadWriter to collect the list, and use that for testing.
Now, this all works fine in simple form, where runCtxt3 is mechanics for
executing via System.Process:
cmds1 :: (MonadError ExecError μ, MonadReader (ProcExecCtxt3 μ) ρ) => ρ
(Producer [CmdSpec] μ ())
cmds1 = systemx (CmdSpec grep ["root", "/etc/passwd"])
cmds1' :: (MonadError ExecError μ, MonadReader (ProcExecCtxt3 μ) ρ) => ρ
(Producer [CmdSpec] μ ())
cmds1' = systemx (CmdSpec grep ["foo", "/etc/motd"])
λ> :t runCtxt3
runCtxt3 :: MonadIO μ => ProcExecCtxt3 μ
λ> runExceptT $ runEffect $ for (runReader (cmds1') runCtxt3) (mapM_
warnCmd)
CMD: /bin/grep foo /etc/motd
/bin/grep: /etc/motd: No such file or directory
Left (ExecError (ExitVal 2))
λ> runExceptT $ runEffect $ for (runReader cmds1 runCtxt3) (mapM_ warnCmd)
CMD: /bin/grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
Right ()
BUT! If I attempt to execute two commands, only the last one gets run:
cmds2 :: (MonadError ExecError μ, MonadReader (ProcExecCtxt3 μ) ρ) => ρ
(Producer [CmdSpec] μ ())
cmds2 = do
systemx grepIt
systemx grepIt2
This is baffling me. I would suspect laziness, but that we're clearly
running within MonadIO, that doesn't apply, right?
I'm sure I'm being a bit dim, but any pointers would be gratefully received.
Yours,
Martyn.
--
You received this message because you are subscribed to the Google Groups "Haskell
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to haskell-pipes+unsubscr...@googlegroups.com.
To post to this group, send email to haskell-pipes@googlegroups.com.