on master help sign in
Added Process effect (#25)

* Added Process effect based on process package * Fixed Haddock: typed-process -> process

commitf3c7e00cbb7c0ad621abea21fee9f6b9d62dbf55 authorMann mit Hut <mmhat@users.noreply.github.com> dateThu 29 Jul 2021, 16:50 (5 years ago) parent3b5a7c0
2 files changed+186
effectful/effectful.cabal+2 effectful/src/Effectful/Process.hs+184
effectful/effectful.cabal+2
@@ -64,6 +64,7 @@ library
6464 build-depends: base >= 4.13 && <5
6565 , async
6666 , effectful-core >= 0.1 && <0.1.1
67+ , process
6768 , resourcet
6869 , unliftio
6970
@@ -71,6 +72,7 @@ library
7172
7273 exposed-modules: Effectful
7374 Effectful.Async
75+ Effectful.Process
7476 Effectful.Resource
7577
7678 reexported-modules: Effectful.Error
effectful/src/Effectful/Process.hsnew file+184
@@ -0,0 +1,184 @@
1+{-# LANGUAGE CPP #-}
2+
3+module Effectful.Process
4+ ( -- * Process effect
5+ Process
6+ , runProcess
7+
8+ -- * Running sub-processes
9+ , createProcess
10+ , createProcess_
11+ , P.shell
12+ , P.proc
13+ , P.CreateProcess(..)
14+ , P.CmdSpec(..)
15+ , P.StdStream(..)
16+ , P.ProcessHandle
17+
18+ -- ** Simpler functions for common tasks
19+ , callProcess
20+ , callCommand
21+ , spawnProcess
22+ , spawnCommand
23+ , readCreateProcess
24+ , readProcess
25+ , readCreateProcessWithExitCode
26+ , readProcessWithExitCode
27+ , withCreateProcess
28+ , cleanupProcess
29+
30+ -- ** Related utilities
31+ , P.showCommandForUser
32+ , P.Pid
33+ , getPid
34+#if MIN_VERSION_process(1,6,12)
35+ , getCurrentPid
36+#endif
37+
38+ -- * Process completion
39+ , waitForProcess
40+ , getProcessExitCode
41+ , terminateProcess
42+ , interruptProcessGroupOf
43+
44+ -- * Interprocess communication
45+ , createPipe
46+ , createPipeFd
47+ ) where
48+
49+import System.Exit (ExitCode)
50+import System.IO (Handle)
51+import System.Posix.Internals (FD)
52+import qualified System.Process as P
53+
54+import Effectful.Internal.Effect
55+import Effectful.Internal.Monad
56+
57+-- | An effect for running child processes using the @process@ library.
58+data Process :: Effect where
59+ Process :: Process m r
60+
61+runProcess :: IOE :> es => Eff (Process : es) a -> Eff es a
62+runProcess = evalEffect (IdE Process)
63+
64+----------------------------------------
65+-- Running sub-processes
66+
67+-- | Lifted 'P.createProcess'.
68+createProcess
69+ :: Process :> es
70+ => P.CreateProcess
71+ -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
72+createProcess = unsafeEff_ . P.createProcess
73+
74+-- | Lifted 'P.createProcess_'.
75+createProcess_
76+ :: Process :> es
77+ => String
78+ -> P.CreateProcess
79+ -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
80+createProcess_ msg = unsafeEff_ . P.createProcess_ msg
81+
82+----------------------------------------
83+-- Simpler functions for common tasks
84+
85+-- | Lifted 'P.callProcess'.
86+callProcess :: Process :> es => FilePath -> [String] -> Eff es ()
87+callProcess fp = unsafeEff_ . P.callProcess fp
88+
89+-- | Lifted 'P.callCommand'.
90+callCommand :: Process :> es => String -> Eff es ()
91+callCommand = unsafeEff_ . P.callCommand
92+
93+-- | Lifted 'P.spawnProcess'.
94+spawnProcess :: Process :> es => FilePath -> [String] -> Eff es P.ProcessHandle
95+spawnProcess fp = unsafeEff_ . P.spawnProcess fp
96+
97+-- | Lifted 'P.spawnCommand'.
98+spawnCommand :: Process :> es => String -> Eff es P.ProcessHandle
99+spawnCommand = unsafeEff_ . P.spawnCommand
100+
101+-- | Lifted 'P.readCreateProcess'.
102+readCreateProcess :: Process :> es => P.CreateProcess -> String -> Eff es String
103+readCreateProcess cp = unsafeEff_ . P.readCreateProcess cp
104+
105+-- | Lifted 'P.readProcess'.
106+readProcess :: Process :> es => FilePath -> [String] -> String -> Eff es String
107+readProcess fp args = unsafeEff_ . P.readProcess fp args
108+
109+-- | Lifted 'P.readCreateProcessWithExitCode'.
110+readCreateProcessWithExitCode
111+ :: Process :> es
112+ => P.CreateProcess
113+ -> String
114+ -> Eff es (ExitCode, String, String)
115+readCreateProcessWithExitCode cp = unsafeEff_ . P.readCreateProcessWithExitCode cp
116+
117+-- | Lifted 'P.readProcessWithExitCode'.
118+readProcessWithExitCode
119+ :: Process :> es
120+ => FilePath
121+ -> [String]
122+ -> String
123+ -> Eff es (ExitCode, String, String)
124+readProcessWithExitCode fp args = unsafeEff_ . P.readProcessWithExitCode fp args
125+
126+-- | Lifted 'P.withCreateProcess'.
127+withCreateProcess
128+ :: Process :> es
129+ => P.CreateProcess
130+ -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> P.ProcessHandle -> Eff es a)
131+ -> Eff es a
132+withCreateProcess cp cb = unsafeEff $ \es ->
133+ unsafeSeqUnliftEff es $ \runInIO ->
134+ P.withCreateProcess cp (\inh outh errh ph -> runInIO $ cb inh outh errh ph)
135+
136+-- | Lifted 'P.cleanupProcess'.
137+cleanupProcess
138+ :: Process :> es
139+ => (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
140+ -> Eff es ()
141+cleanupProcess = unsafeEff_ . P.cleanupProcess
142+
143+----------------------------------------
144+-- Related utilities
145+
146+-- | Lifted 'P.getPid'.
147+getPid :: Process :> es => P.ProcessHandle -> Eff es (Maybe P.Pid)
148+getPid = unsafeEff_ . P.getPid
149+
150+#if MIN_VERSION_process(1,6,12)
151+-- | Lifted 'P.getCurrentPid'.
152+getCurrentPid :: Process :> es => Eff es P.Pid
153+getCurrentPid = unsafeEff_ P.getCurrentPid
154+#endif
155+
156+----------------------------------------
157+-- Process completion
158+
159+-- | Lifted 'P.waitForProcess'.
160+waitForProcess :: Process :> es => P.ProcessHandle -> Eff es ExitCode
161+waitForProcess = unsafeEff_ . P.waitForProcess
162+
163+-- | Lifted 'P.getProcessExitCode'.
164+getProcessExitCode :: Process :> es => P.ProcessHandle -> Eff es (Maybe ExitCode)
165+getProcessExitCode = unsafeEff_ . P.getProcessExitCode
166+
167+-- | Lifted 'P.terminateProcess'.
168+terminateProcess :: Process :> es => P.ProcessHandle -> Eff es ()
169+terminateProcess = unsafeEff_ . P.terminateProcess
170+
171+-- | Lifted 'P.interruptProcessGroupOf'.
172+interruptProcessGroupOf :: Process :> es => P.ProcessHandle -> Eff es ()
173+interruptProcessGroupOf = unsafeEff_ . P.interruptProcessGroupOf
174+
175+----------------------------------------
176+-- Interprocess communication
177+
178+-- | Lifted 'P.createPipe'.
179+createPipe :: Process :> es => Eff es (Handle, Handle)
180+createPipe = unsafeEff_ P.createPipe
181+
182+-- | Lifted 'P.createPipeFd'.
183+createPipeFd :: Process :> es => Eff es (FD, FD)
184+createPipeFd = unsafeEff_ P.createPipeFd