I am looking for a Haskell design to compose a chain of monadic actions (usually IO) in a manner, that later actions are dependent on previous ones but in some cases can be executed before they have finished.
The solution I came up with so far is:
type Future m a = m (m a)
Read: a monadic action, which starts some process and returns an action which will return the result of that process (possibly by waiting for this process to finish).
So in some chain a >>= b >>= c b gets an action returning a’s result. If b evaluates this action it waits for a to finish, otherwise it will be run in parallel. That also means that if some action does not require the result of the previous one as argument, it does not depend on it by definition, so the dependencies are explicit.
Some example code:
date :: Future IO String -- long process to find out the date
date = do
print "attempting to get date" -- will usually start some thread or process to compute the date
return (print "today") -- will wait for this thread or process and return the computed date
main = do
d <- date -- starts recieving the date
print "foo" -- some other process
d >>= print -- waits until the date has been computed and prints it out
Output:
"attempting to get date"
"foo"
"today"
There is a problem through: if an action decides to wait for the previous one it will always be dependent on all the others before (in my case). But in the example above if c decides to wait for b but b did not decide to wait for a, c may start before a has finished, which should not happen.
As a solution I wrote another combining operator:
(>=>) :: Monad m => Future m a -> (m a -> Future m b) -> Future m b
a >=> f = do
r1 <- a
r2 <- f r1
return (r1 >> r2)
So this will combine the “wait actions” and a >=> b >=> c will work just fine, if c waits for b this wait action will also wait for a.
However there is another problem with this approach (apart from that you need to remember to use >=> instead of >>=): the wait actions may be evaluated many times.
If b waits for a and c waits for b the wait for b will be connected to the wait for a nevertheless and thus the wait for a will be executed twice.
The actual problem is in >=>: f r1 may evaluate r1 in wich case it does not need to be sequenced with r2 in the return statement (as it already was executed and thus a has finished). But it also might not, I cannot know.
So what I basically want is exactly this but without the possibility to run the wait actions several times. Unfortunately I am not very experienced in functional design.
So I hope you can enlighten me in some way how to augment or change my design or point me to a different, more flexible approach.
Edit According to the answers so far I like to give some more clarification about what I actually want:
I do not want to defer (or even skip) the execution of actions, neither do I require threads or similar parallelism features. Actually I am calling external processes. An example would be
backup :: Future IO ExitCode
backup = do
pid <- startProcess "backup"
return (waitForProcessAndGetExitCode pid)
When I now chain actions like backup >=> otherAction, otherAction can run while the backup is running (which saves much time overall). But otherAction may require the backup to be completed, in which case it can use its parameter to wait for the backup and to check whether it was successful. Either way the backup has to be executed.
I am now looking for a nice general solution, ideally not tied to the IO monad.
Update I found a solution that worked for me. I described it in a seperate answer below.
I'm pretty sure you actually wanted this signature:
(>>=) :: Future m a -> (a -> Future m b) -> Future m b
Here's how you implement what you want:
import Control.Concurrent
import Control.Monad
import Control.Monad.Trans
newtype Future m a = Future { runFuture :: m (m a) }
instance (Monad m) => Monad (Future m) where
return = Future . return . return
m >>= f = Future $ do
fut1 <- runFuture m
return $ join $ join $ liftM (runFuture . f) fut1
instance MonadTrans Future where
lift = Future . liftM return
In other words, Future is a monad transformer, and nothing about its implementation is specialized to the IO monad. However, the following example will show how you use it in conjunction with the IO monad to chain futures:
parallel :: IO a -> Future IO a
parallel m = Future $ do
v <- newEmptyMVar
forkIO $ m >>= putMVar v
return $ takeMVar v
future1 = parallel $ do
threadDelay 1000000
putStrLn "Hello, World"
return 1
future2 n = parallel $ do
threadDelay 1000000
print n
return 2
future3 = future1 >>= future2
main = do
f <- runFuture future3
putStrLn "I'm waiting..."
r <- f
print r
I haven't yet proven that it satisfies the monad laws or the monad transformer laws, but I will try to do that and I will update you on whether or not it checks out. Until then, there might be a misplaced join somewhere in there.
Edit: Nope! Not even close. It definitely does not satisfy the monad laws. I don't know if I was close or not, but just assume this answer is incorrect for now. However, I'm kind of intrigued now and wonder if it's possible.
Perhaps one possibility is to refuse to even run f until its output is demanded:
mma >=> fab = return $ do
ma <- mma
b <- fab ma
b
Depending on just what you want, it may be important to run mma first:
mma >=> fab = do
ma <- mma
return $ do
b <- fab ma
b
If you add the restriction that you have a MonadIO instance for m, you can do something like this (from memory, untested):
share :: IO a -> IO (IO a)
share m = do
ref <- newIORef Nothing
let reader = do
cached <- readIORef ref
case cached of
Just a -> return a
Nothing -> m >>= \a -> writeIORef ref (Just a) >> return a
return reader
You can change this to share2 :: IO a -> IO a by wrapping the IORef creation in unsafePerformIO, and it's simple to generalize to any MonadIO instance.
But, depending on your problem, you might be better off with something like threads or IVar.
For cases, when you want to spark some threads and at some moment to collect results, check http://hackage.haskell.org/packages/archive/base/4.5.1.0/doc/html/Control-Concurrent-SampleVar.html and http://hackage.haskell.org/packages/archive/base/4.5.1.0/doc/html/Control-Concurrent.html#g:2 , as they seems relevant
For cases, when you need execute actions on demand, you may find this code useful
Not checked in GHC but should work after typos fixed
module Promise (SuspendedAction, createSuspendedAction, getValueFromSuspendedAction)
import Data.IORef
data Promise a = Suspended (IO a) | Done a
data SuspendedAction = SA (IORef (Promise a))
createSuspendedAction :: m a -> m (SuspendedAction a)
createSuspendedAction act = newIORef (Suspended act)
readSuspendedAction :: SuspendedAction a -> m a
readSuspendedAction (SA ref) = readIORef ref >>= \suspended -> case suspended of
Done a -> return a
Suspended sact -> sact >>= \rv -> writeIORef ref (Done rv) >> return rv
BTW, check hackage carefully, there was package which allow to execute IO actions lazily while respecting their order.
I found a solution myself, albeit not entirely for the problem I have postet.
I realized that I have to know somehow beforehand, whether or not an action is dependant from the one before. I tried various approaches and evenually came up with something I am going to describe now.
My solution allows to write code like
a :: Process IO x ()
a = independant $ do
print "start a"
return $ print "end a"
b :: Process IO x Int
b = independant $ do
print "start b"
return $ print "end b" >> return 0
c :: Process IO Int ()
c = dependant $ \x -> do
print $ "start c with " ++ show x
return $ print ("end c, started with " ++ show x)
chain = a >~ b >~ c
main = exec chain
-- outputs:
"start a" "start b" "end a" "end b" "start c with 0" "end c, started with 0"
(more examples below)
I used the following types
type Future m a = m (m a)
type Action m a b = a -> Future m b
type Process m a b = forall c. Action m c a -> Action m c b -- will need -XRank2Types
with the following primitives:
-- sequences f after g, f is dependant of g and gets its result
-- dependant :: Monad m => Action m a b -> Action m c a -> Action c b
dependant :: Monad m => Action m a b -> Process m a b
dependant f g a = join (g a) >>= f
-- sequences f after g, f is independant of g
independant :: Monad m => Future m a -> Process m b a
independant f g a = do
w1 <- g a
w2 <- f
return (w1 >> w2)
-- concenation of processes
(>~) = flip (.)
This approach allows other primitives for easier handling as well, for instance:
-- lifts a pure function into an action
pureA :: Monad m => (a -> b) -> Action m a b
pureA f a = return . return $ f a
-- makes an action wich always returns the same result
constA :: Monad m => b -> Action m a b
constA = pureA . const
-- no operation action
nop :: Monad m => Action m a ()
nop = constA ()
-- puts a sequence point
wait :: Monad m => Process m a a
wait = dependant $ pureA id
-- modify its result with a pure function
modify :: (Monad m, Functor m) => (a -> b) -> Process m a b
modify f act a = do
x <- act a
return (fmap f x)
-- makes a process, wich always returns the same result
constP :: (Monad m, Functor m) => b -> Process m a b
constP = modify . const
And finally a function to run a process:
-- executes a process
exec :: Monad m => Process m () b -> m b
exec p = join $ p nop undefined
So a few a little more complex examples:
simleI :: String -> a -> Process IO b a
simpleI name r = independant $ do
print ("start " ++ name)
return $ print ("end " ++ name) >> return r
simpleD :: (Show a, Show b) => String -> (a -> b) -> Process IO a b
simpleD name f = dependant $ \a -> do
print ("start " ++ name ++ " with " ++ show a)
let r = f a
return $ print ("end " ++ name ++ " with " ++ show r ++ " (started with " ++ show a ++ ")") >> return r
a = simpleI "a" ()
b = simpleI "b" 42
c = simpleD "c" (+1)
d = simpleI "d" ()
chain1 = a >~ b >~ c >~ d -- == d . c . b . a
chain2 = a >~ wait >~ b >~ c >~ d
chain3 = a >~ b >~ modify (+1) >~ c >~ d
main = do
exec chain1
print "---"
exec chain2
print "---"
exec chain3
Output:
"start a"
"start b"
"end a"
"end b"
"start c with 42"
"start d"
"end c with 43 (started with 42)"
"end d"
"---"
"start a"
"end a"
"start b"
"end b"
"start c with 42"
"start d"
"end c with 43 (started with 42)"
"end d"
"---"
"start a"
"start b"
"end a"
"end b"
"start c with 43"
"start d"
"end c with 44 (started with 43)"
"end d"
This is almost exactly what I want.
I am a little curious how to classify Action and Process. They are not monads. They may be Arrows, but I am too unfamiliar with Arrows to tell. Process may be an Applicative with fmap = modify and pure = const . constA oder something like that.
Please feel free to comment anything that comes in your mind about my approach, especially how to extend or simplify it.
Related
Hi I'm looking for a good way to allow a monad stack to skip the remaining actions, without skipping out entirely. Kind of like return in C-family langauges.
For example, let's say I'm using monadic actions for the side effects
type MyMonad = ??
doStuff :: MyMonad ()
doStuff = do
r <- doSomething
-- equivalent to if (r == "X") return; in C
dontGoPastHereIf (r == "X")
doSomeSideEffects r
So I want it to only perform doSomeSideEffects on some condition.
I know you can do something close to this with guard and when already. Is it possible to do without nesting though?
ExceptT already allows you to exit the normal flow and return with an early result. But with ExceptT the error / skip will propogate. I want to only skip the rest of the steps in the local function
doTwoSteps :: MyMonad ()
doTwoSteps = do
-- if I used ExceptT, an error in the first function will skip the second.
-- But I still want to do the second step here
doStuff
doStuff
It seems like bind >>= already does this. At least it's certainly within the possibilities of a monad, but I'm not sure how to do with monad transformers.
Here's a more complete example. This system is supposed to perform a "workflow". Each step can result in a response, which is supposed to stop the entire workflow and respond (ExceptT).
The workflow can be restarted by passing ApplicationState. If a step has a previous Continue we can skip the logic for that step, but we still need to execute the next step.
Is there a better way to do this? Is there some monad transformer or a way to define my Flow monad such that I can run checkShouldSkip without passing in an action?
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
module Main where
import Control.Monad.Except (throwError, ExceptT)
import Control.Monad.State (gets, StateT, modify)
import Data.Text (Text)
data ApplicationState = ApplicationState
{ step1Result :: Maybe StepResult
, step2Result :: Maybe StepResult
} deriving (Show, Eq)
data StepResult
= Stop
| Continue
deriving (Show, Eq)
type Flow a = StateT ApplicationState (ExceptT Text IO) a
flow :: Flow ()
flow = do
step1
step2
step1 :: Flow ()
step1 = do
ms <- gets step1Result
checkShouldSkip ms $ do
info <- getStuffFromAServer
let r = runSomeLogic info
modify $ setStep1 $ Just r
checkShouldRespond r
where
getStuffFromAServer = undefined
runSomeLogic _ = undefined
setStep1 r s = s { step1Result = r }
step2 :: Flow ()
step2 = do
ms <- gets step2Result
checkShouldSkip ms $ do
-- this will run some different logic, eventually resulting in a step result
r <- getStuffAndRunLogic
modify $ setStep2 $ Just r
checkShouldRespond r
where
getStuffAndRunLogic = undefined
setStep2 r s = s { step2Result = r }
checkShouldSkip :: Maybe StepResult -> Flow () -> Flow ()
checkShouldSkip (Just Continue) _ = pure () -- skip the logic, continue
checkShouldSkip (Just Stop) _ = respond "Stop" -- skip the logic, stop everything
checkShouldSkip Nothing a = a -- run the action
checkShouldRespond :: StepResult -> Flow ()
checkShouldRespond Continue = pure ()
checkShouldRespond Stop = respond "Stop" -- if a response, stop all execution
-- rename because these aren't really errors, I just want to stop everything
respond :: Text -> Flow ()
respond t = throwError t
The other answer is great! I wanted to talk a little bit about how exactly the continuation solution works so I wrote up this weird big thing. Hope it helps.
Act I: A Trap Is Laid
We begin our journey in the low rolling plains of IO, our favorite state monad:
module Lib where
step1 :: IO String
step1 = do
print "step1 - A"
print "step1 - B"
pure "--step1 result--"
step2 :: String -> IO String
step2 input = do
print input
print "step2 - A"
print "step2 - B"
pure "--step2 complete--"
main :: IO ()
main = do
result <- step1 >>= step2
print "--done--"
print result
We want to ascend upward and find a way of returning early from step one. Our first attempt is to introduce some sort of questionably-typed escape mechanism:
step1 :: (String -> ???) -> IO String
step1 escape = do
print "step1 - A"
escape "escaped!"
print "step1 - B"
pure "--step1 result--"
We cross our fingers, hoping that the string we pass to escape will end up as the string in IO String, and ponder what exactly can fill in those pesky question marks.
It seems to us that we need to hijack the >>= here if we are to have any hope of wresting the control flow away from the IO monad. We cautiously guess that we will need our own monad transformer.
newtype StrangeT inner a =
StrangeT { runStrangeT :: a -> ??? }
lift :: IO a -> StrangeT IO a
lift io =
StrangeT (\trapDoor -> io >>= trapDoor)
escape :: a -> StrangeT IO a
escape a =
StrangeT (\trapDoorA -> trapDoorA a)
step1 :: StrangeT IO String
step1 = do
lift (print "step1 - A")
escape "escaped!"
lift (print "step1 - B")
pure "--step1 result--"
We can think of trapDoorA as an escape mechanism guarded by a key, the key being any value of type a. Once the door is open we fall through into the next step of the computation.
What type to insert for the question marks? We have sort of boxed ourselves into a corner; in order for this code to compile we it can only be:
newtype StrangeT inner a =
StrangeT { runStrangeT :: (a -> inner a) -> inner a }
Act II: Stranger Still
We now need to instance Monad (StrangeT inner). Unfortunately we are going to run into a big problem. StrangeT is not a functor!
The reason for this is that "a" appears in the "negative position":
newtype StrangeT inner a =
StrangeT { runStrangeT :: (a -> inner a) -> inner a }
-- ^^^^^^^
-- :(
(For a full discussion of this topic see What is a contravariant functor?.)
We can employ a nasty trick, which is to split the "negatives" and the "positives" into two different type variables (a and result):
newtype StrangeT result inner a =
StrangeT { runStrangeT :: (a -> inner result) -> inner result }
lift :: IO a -> StrangeT whatever IO a
lift io = StrangeT (\trapDoor -> io >>= trapDoor)
escape :: a -> StrangeT whatever IO a
escape x = StrangeT (\trapDoor -> trapDoor x)
This makes everything possible. We can now instance Functor, Applicative, and Monad. Rather than trying to puzzle out the answers though, we will simply let the type checker take over. Any answer that type checks will be the right one.
instance Functor (StrangeT result inner) where
fmap a2b (StrangeT strange) =
StrangeT $ \trapDoor -> strange (\a -> trapDoor (a2b a))
-- ^^^^^^^^
-- b -> inner result
Train of logic:
trapDoor is the only way to build an inner result value.
It needs a value of type b.
We have a2b :: a -> b and a :: a.
instance Applicative (StrangeT result inner) where
pure :: a -> StrangeT result inner a
pure a = StrangeT $ \trapDoor -> trapDoor a
(<*>) :: StrangeT result inner (a -> b) ->
StrangeT result inner a ->
StrangeT result inner b
(StrangeT strangeA2B) <*> (StrangeT strangeA) =
-- ^^^^^^^^^^ ^^^^^^^^
-- (b -> inner result) -> inner result
-- (a -> inner result) -> inner result
StrangeT (\trapDoorB -> strangeA2B (\a2b -> strangeA (\a -> trapDoorB (a2b a))))
-- ^^^^^^^^
-- b -> inner result
Train of logic:
We have trapDoorB :: b -> inner result (the only way to construct inner result), a2b :: a -> b, and a :: a.
We need to construct a StrangeT result inner b;
We therefore must at some point evaluate trapDoorB (a2b a).
The monadic instance is about as difficult:
instance Monad (StrangeT result inner) where
(StrangeT strangeA) >>= a2strangeB =
-- ^^^^^^^^
-- (a -> inner result) -> inner result
StrangeT
(\trapDoorB -> strangeA (\a -> let StrangeT strangeB = a2strangeB a in strangeB (\b -> trapDoorB b)))
-- ^^^^^^^^^ ^^^^^^^^
-- b -> inner result (b -> inner result) -> inner result
There is only one way to construct inner result, which by falling through trapDoorB, so everything else is built toward that singular goal.
Act III: A Fumble
We have defined a monad transformer without really knowing what it does or how it works! We simply smashed together the types that looked right.
It would behoove us then to see it in action:
main :: IO ()
main = do
_ <- runStrangeT (step1 >>= step2) (\a -> pure a)
print "--done--"
print result
This results in the following output:
λ> main
"step1 - A"
"step1 - B"
"--step1 result--"
"step2 - A"
"step2 - B"
"--done--"
"--step2 result--"
How frustrating! We are right where we started from.
However, something peculiar happens if we define this function:
escape :: a -> StrangeT whatever IO a
escape x = StrangeT (\trapDoor -> trapDoor x)
escapeWeirdly :: a -> StrangeT whatever IO a
escapeWeirdly x = StrangeT (\trapDoor -> trapDoor x >> trapDoor x >> trapDoor x)
step1 :: StrangeT String IO String
step1 = do
lift (print "step1 - A")
escapeWeirdly "--step1 exit--"
lift (print "step1 - B")
pure "--step1 result--"
Output:
λ> main
"step1 - A"
"step1 - B" <- trap door call #1
"--step1 result--"
"step2 - A"
"step2 - B"
"step1 - B" <- trap door call #2
"--step1 result--"
"step2 - A"
"step2 - B"
"step1 - B" <- trap door call #3
"--step1 result--"
"step2 - A"
"step2 - B"
"--done--"
"--step2 result--"
step2 runs three times! It seems that "trapDoor" encodes some notion of "everything after this point in the control flow." Calling it once runs everything after it once. Calling it three times runs everything after it three times. Calling it zero times...
cut :: a -> StrangeT a IO a
cut x = StrangeT (\_ -> return x)
step1 :: (String -> StrangeT String IO String) -> StrangeT String IO String
step1 exit = do
lift (print "step1 - A")
cut "--step1 exit--"
lift (print "step1 - B")
pure "--step1 result--"
main :: IO ()
main = do
result <- runStrangeT (step1 undefined >>= step2) pure
print "--done--"
print result
Output:
λ> main
"step1 - A"
"--done--"
"--step1 exit--"
Nothing runs! This is incredibly close to what we need.
Act IV: Success and the Price Thereof
What if we could mark a do-block of StrangeT actions as needing an early exit? Something very similar to our original escape mechanism:
step1 = withEscape $ \escape -> do
lift (print "step1 - A")
escape "--step1 exit--"
lift (print "step1 - B")
pure "--step1 result--"
What withEscape does is it runs the do-block as written until someone calls escape, at which point the rest of the computation is aborted but any computation outside the withEscape (namely Step Two here) runs as-is.
This helper must have a type of:
withEscape :: (??? -> StrangeT result inner a) -> StrangeT result inner a
Almost the exact same leap of faith we made when we went from m a to (a -> m a) -> m a.
Since we are passing a String to escape and binding the result of that computation to the next line of the do-block, we can now fill in those question marks:
withEscape :: ((a -> StrangeT result inner whatever) -> StrangeT result inner a)
-> StrangeT result inner a
A tricksy type! We are going to have to navigate by type again to find the definition:
-- We have to call f at some point, and trapDoorA
-- is the only way to construct an inner result.
withEscape f =
StrangeT (\trapDoorA -> let StrangeT strangeA = f ??? in strangeA trapDoorA)
-- f is passed the early exit value
withEscape f =
StrangeT (\trapDoorA ->
let StrangeT strangeA = f (\a -> ???) in strangeA trapDoorA)
-- We need to construct a StrangeT value
withEscape f =
StrangeT (\trapDoorA ->
let StrangeT strangeA = f (\a -> StrangeT (\trapDoorWhatever -> ???)) in
strangeA trapDoorA)
-- We are going to *ignore* the trapDoorWhatever
-- we are supposed to fall into, and *instead*
-- fall through our original trapDoorA.
withEscape f =
StrangeT (\trapDoorA ->
let StrangeT strangeA = f (\a -> StrangeT (\_ -> trapDoor a)) in
strangeA trapDoorA)
What happened here is that we stumbled onto a solution that gives us two trap doors. Instead of falling through the first door (which would make the helper boil down to something like pure in that it would resume normal control flow) we chose to fall through the original door we built for ourselves. Fans of the movie Primer will recognize this as the original sin; normal people might just view all this with a confused look on their face.
Regardless, this works:
step1 :: StrangeT String IO String
step1 =
withEscape $ \escape -> do
lift (print "step1 - A")
escape "--step1 exit--"
lift (print "step1 - B")
pure "--step1 result--"
step2 :: String -> StrangeT String IO String
step2 result = do
lift (print result)
lift (print "step2 - A")
lift (print "step2 - B")
pure "--step2 result--"
main :: IO ()
main = do
result <- runStrangeT (step1 >>= step2) pure
print "--done--"
print result
Output:
λ> main
"step1 - A" <- early exit
"--step1 exit--" <- step2 runs
"step2 - A"
"step2 - B"
"--done--" <- back to main
"--step2 result--"
Summary
As telegraphed, this is the ContT monad and can be found packaged in the transfomers package. What we have been calling trap doors are really continuations.
withEscape is better known as callCC (call with current continuation); it lets you give the current continuation at the time you called callCC a name (escape in our examples); when you activate the continuation it allows you to return a value immediately.
You can implement a great deal many things with continuations, including early returns and exceptions and generators and god knows what else. We have yet to even talk about delimited continuations (shift and reset). They represent something primal and fundamental to the structure of computer programming.
For more information, see the series of papers linked from Oleg Kiselyov's website. There is much much more to be said about continuations.
Should you ever actually do this in real life?
Probably not. ExceptT tends to create fewer headaches in the long run.
But is ExceptT cooler than ContT?
Hardly.
You can do this with ExceptT if you’re willing to wrap the scope from which you want to be able to exit:
type EarlyReturnT m a = ExceptT a m a
withEarlyReturn :: (Functor m) => EarlyReturnT m a -> m a
withEarlyReturn = fmap (either id id) . runExceptT
earlyReturn :: (Applicative m) => a -> EarlyReturnT m a
earlyReturn = ExceptT . pure . Left
For example:
doStuff :: Bool -> IO String
doStuff x = withEarlyReturn $ do
lift $ putStrLn "hello"
when x $ earlyReturn "beans"
lift $ putStrLn "goodbye"
return "eggs"
> doStuff False
hello
goodbye
"eggs"
> doStuff True
hello
"beans"
Or with ContT, where the “early return” is a continuation.
type EarlyReturnT m a = ContT a m a
withEarlyReturn
:: (Applicative m)
=> ((a -> EarlyReturnT m a) -> EarlyReturnT m a)
-> m a
withEarlyReturn = flip runContT pure . callCC
doStuff :: Bool -> IO String
doStuff x = withEarlyReturn $ \ earlyReturn -> do
lift $ putStrLn "hello"
when x $ earlyReturn "beans"
lift $ putStrLn "goodbye"
return "eggs"
I'm trying to work out if it's possible to write an abstraction for the following situation. Suppose I have a type a with function a -> m Bool e.g. MVar Bool and readMVar. To abstract this concept out I create a newtype wrapper for the type and its function:
newtype MPredicate m a = MPredicate (a,a -> m Bool)
I can define a fairly simple operation like so:
doUnless :: (Monad m) => Predicate m a -> m () -> m ()
doUnless (MPredicate (a,mg)) g = mg a >>= \b -> unless b g
main = do
b <- newMVar False
let mpred = MPredicate (b,readMVar)
doUnless mpred (print "foo")
In this case doUnless would print "foo". Aside: I'm not sure whether a type class might be more appropriate to use instead of a newtype.
Now take the code below, which outputs an incrementing number then waits a second and repeats. It does this until it receives a "turn off" instruction via the MVar.
foobar :: MVar Bool -> IO ()
foobar mvb = foobar' 0
where
foobar' :: Int -> IO ()
foobar' x = readMVar mvb >>= \b -> unless b $ do
let x' = x + 1
print x'
threadDelay 1000000
foobar' x'
goTillEnter :: MVar Bool -> IO ()
goTillEnter mv = do
_ <- getLine
_ <- takeMVar mv
putMVar mv True
main = do
mvb <- newMVar False
forkIO $ foobar mvb
goTillEnter mvb
Is it possible to refactor foobar so that it uses MPredicate and doUnless?
Ignoring the actual implementation of foobar' I can think of a simplistic way of doing something similar:
cycleUnless :: x -> (x -> x) -> MPredicate m a -> m ()
cycleUnless x g mp = let g' x' = doUnless mp (g' $ g x')
in g' $ g x
Aside: I feel like fix could be used to make the above neater, though I still have trouble working out how to use it
But cycleUnless won't work on foobar because the type of foobar' is actually Int -> IO () (from the use of print x').
I'd also like to take this abstraction further, so that it can work threading around a Monad. With stateful Monads it becomes even harder. E.g.
-- EDIT: Updated the below to show an example of how the code is used
{- ^^ some parent function which has the MVar ^^ -}
cycleST :: (forall s. ST s (STArray s Int Int)) -> IO ()
cycleST sta = readMVar mvb >>= \b -> unless b $ do
n <- readMVar someMVar
i <- readMVar someOtherMVar
let sta' = do
arr <- sta
x <- readArray arr n
writeArray arr n (x + i)
return arr
y = runSTArray sta'
print y
cycleST sta'
I have something similar to the above working with RankNTypes. Now there's the additional problem of trying to thread through the existential s, which is not likely to type check if threaded around through an abstraction the likes of cycleUnless.
Additionally, this is simplified to make the question easier to answer. I also use a set of semaphores built from MVar [MVar ()] similar to the skip channel example in the MVar module. If I can solve the above problem I plan to generalize the semaphores as well.
Ultimately this isn't some blocking problem. I have 3 components of the application operating in a cycle off the same MVar Bool but doing fairly different asynchronous tasks. In each one I have written a custom function that performs the appropriate cycle.
I'm trying to learn the "don't write large programs" approach. What I'd like to do is refactor chunks of code into their own mini libraries so that I'm not building a large program but assembling lots of small ones. But so far this particular abstraction is escaping me.
Any thoughts on how I might go about this are very much appreciated!
You want to cleanly combine a stateful action having side effects, a delay, and an independent stopping condition.
The iterative monad transformer from the free package can be useful in these cases.
This monad transformer lets you describe a (possibly nonending) computation as a series of discrete steps. And what's better, it let's you interleave "stepped" computations using mplus. The combined computation stops when any of the individual computations stops.
Some preliminary imports:
import Data.Bool
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Iter (delay,untilJust,IterT,retract,cutoff)
import Control.Concurrent
Your foobar function could be understood as a "sum" of three things:
A computation that does nothing but reading from the MVar at each step, and finishes when the Mvar is True.
untilTrue :: (MonadIO m) => MVar Bool -> IterT m ()
untilTrue = untilJust . liftM guard . liftIO . readMVar
An infinite computation that takes a delay at each step.
delays :: (MonadIO m) => Int -> IterT m a
delays = forever . delay . liftIO . threadDelay
An infinite computation that prints an increasing series of numbers.
foobar' :: (MonadIO m) => Int -> IterT m a
foobar' x = do
let x' = x + 1
liftIO (print x')
delay (foobar' x')
With this in place, we can write foobar as:
foobar :: (MonadIO m) => MVar Bool -> m ()
foobar v = retract (delays 1000000 `mplus` untilTrue v `mplus` foobar' 0)
The neat thing about this is that you can change or remove the "stopping condition" and the delay very easily.
Some clarifications:
The delay function is not a delay in IO, it just tells the iterative monad transformer to "put the argument in a separate step".
retract brings you back from the iterative monad transformer to the base monad. It's like saying "I don't care about the steps, just run the computation". You can combine retract with cutoff if you want to limit the maximum number of iterations.
untilJustconverts a value m (Maybe a) of the base monad into a IterT m a by retrying in each step until a Just is returned. Of course, this risks non-termination!
MPredicate is rather superfluous here; m Bool can be used instead. The monad-loops package contains plenty of control structures with m Bool conditions. whileM_ in particular is applicable here, although we need to include a State monad for the Int that we're threading around:
import Control.Monad.State
import Control.Monad.Loops
import Control.Applicative
foobar :: MVar Bool -> IO ()
foobar mvb = (`evalStateT` (0 :: Int)) $
whileM_ (not <$> lift (readMVar mvb)) $ do
modify (+1)
lift . print =<< get
lift $ threadDelay 1000000
Alternatively, we can use a monadic version of unless. For some reason monad-loops doesn't export such a function, so let's write it:
unlessM :: Monad m => m Bool -> m () -> m ()
unlessM mb action = do
b <- mb
unless b action
It's somewhat more convenient and more modular in a monadic setting, since we can always go from a pure Bool to m Bool, but not vice versa.
foobar :: MVar Bool -> IO ()
foobar mvb = go 0
where
go :: Int -> IO ()
go x = unlessM (readMVar mvb) $ do
let x' = x + 1
print x'
threadDelay 1000000
go x'
You mentioned fix; sometimes people indeed use it for ad-hoc monadic loops, for example:
printUntil0 :: IO ()
printUntil0 =
putStrLn "hello"
fix $ \loop -> do
n <- fmap read getLine :: IO Int
print n
when (n /= 0) loop
putStrLn "bye"
With some juggling it's possible to use fix with multi-argument functions. In the case of foobar:
foobar :: MVar Bool -> IO ()
foobar mvb = ($(0 :: Int)) $ fix $ \loop x -> do
unlessM (readMVar mvb) $ do
let x' = x + 1
print x'
threadDelay 1000000
loop x'
I'm not sure what's your MPredicate is doing.
First, instead of newtyping a tuple, it's probably better to use a normal algebric data type
data MPredicate a m = MPredicate a (a -> m Bool)
Second, the way you use it, MPredicate is equivalent to m Bool.
Haskell is lazzy, therefore there is no need to pass, a function and it's argument (even though
it's usefull with strict languages). Just pass the result, and the function will be called when needed.
I mean, instead of passing (x, f) around, just pass f x
Of course, if you are not trying to delay the evaluation and really need at some point, the argument or the function as well as the result, a tuple is fine.
Anyway, in the case your MPredicate is only there to delay the function evaluation, MPredicat reduces to m Bool and doUnless to unless.
Your first example is strictly equivalent :
main = do
b <- newMVar False
unless (readMVar b) (print "foo")
Now, if you want to loop a monad until a condition is reach (or equivalent) you should have a look at the monad-loop package. What you are looking it at is probably untilM_ or equivalent.
I'm getting started with Netwire version 5.
I have no problem writing all the wires I want to transform my inputs into my outputs.
Now the time has come to write the IO wrapper to tie in my real-world inputs, and I am a bit confused.
Am I supposed to create a custom session type for the s parameter of Wire s e m a b and embed my sensor values in there?
If so, I have these questions:
What's up with the Monoid s context of class (Monoid s, Real t) => HasTime t s | s -> t? What is it used for?
I was thinking of tacking on a Map String Double with my sensor readings, but how should my monoid crunch the dictionaries? Should it be left-biased? Right-biased? None of the above?
If not, what am I supposed to do? I want to end up with wires of the form Wire s InhibitionReason Identity () Double for some s, representing my input.
It's my understanding that I don't want or need to use the monadic m parameter of Wire for this purpose, allowing the wires themselves to be pure and confining the IO to the code that steps through the top-level wire(s). Is this incorrect?
The simplest way to put data into a Wire s e m a b is via the input a. It's possible, through the use of WPure or WGen to get data out of the state delta s or the underlying Monad m, but these take us further away from the main abstractions. The main abstractions are Arrow and Category, which only know about a b, and not about s e m.
Here's an example of a very simple program, providing input as the input a. double is the outermost wire of the program. repl is a small read-eval-print loop that calls stepWire to run the wire.
import FRP.Netwire
import Control.Wire.Core
import Prelude hiding (id, (.))
double :: Arrow a => a [x] [x]
double = arr (\xs -> xs ++ xs)
repl :: Wire (Timed Int ()) e IO String String -> IO ()
repl w = do
a <- getLine
(eb, w') <- stepWire w (Timed 1 ()) (Right a)
putStrLn . either (const "Inhibited") id $ eb
repl w'
main = repl double
Notice that we pass in the time difference to stepWire, not the total elapsed time. We can check that this is the correct thing to do by running a different top-level wire.
timeString :: (HasTime t s, Show t, Monad m) => Wire s e m a String
timeString = arr show . time
main = repl timeString
Which has the desired output:
a
1
b
2
c
3
I just solved this in an Arrow way, so this might be more composible. You can read my posts if you like. Kleisli Arrow in Netwire 5? and Console interactivity in Netwire?. The second post has a complete interactive program
First, you need this to lift Kleisli functions (That is, anything a -> m b):
mkKleisli :: (Monad m, Monoid e) => (a -> m b) -> Wire s e m a b
mkKleisli f = mkGen_ $ \a -> liftM Right $ f a
Then, assuming you want to get characters from terminal, you can lift hGetChar by doing this:
inputWire :: Wire s () IO () Char
inputWire = mkKleisli $ \_ -> hGetChar stdin
I haven't tested this runWire function (I just stripped code off from my previous posts), but it should run your wires:
runWire :: (Monad m) => Session m s -> Wire s e m () () -> m ()
runWire s w = do
(ds, s') <- stepSession s
-- | You don't really care about the () returned
(_, w') <- stepWire w ds (Right ())
runWire s' w'
You can compose the input wire wherever you like like any other Wires or Arrows. In my example, I did this (don't just copy, other parts of the program are different):
mainWire = proc _ -> do
c <- inputWire -< ()
q <- quitWire -< c
outputWire -< c
returnA -< q
Or, one-liner:
mainWire = inputWire >>> (quitWire &&& outputWire) >>> arr (\(q,_) -> q)
I am working on designing a Haskell module that is designed solve a math problem, which may have various parameterizations. The module exports a function:
run_and_output_parameterization :: ProblemParams -> String -> IO ()
where the idea is that ProblemParams objects will be generated in some "controller" and called as follows:
map (\(pp, name) -> run_and_output_parameterization pp name) (zip pp_list names_list)
My question is, within the module, there are some functions such as indexing functions which I would like to partially apply for a particular parameterization. For example,
evenly_spaced_point_approx :: Int -> Int -> Int -> Double -> Double -> Int
evenly_spaced_point_approx xmin xmax xstep_i xstep_d target = pt
where
pt = max (min (round (target/xstep_d) * xstep_i) xmax) xmin
evenly_spaced_si_approx target = evenly_spaced_point_approx (_pp_si_min pp) (_pp_si_max pp) (_pp_nstep_s pp) (_pp_nstep_sd pp) target
evenly_spaced_wi_approx target = evenly_spaced_point_approx (_pp_wi_min pp) (_pp_wi_max pp) (_pp_nstep_w pp) (_pp_nstep_wd pp) target
I would like to use the functions evenly_spaced_si_approx and evenly_spaced_wi_approx within the module for a particular ProblemParameter data structure (called pp).
Is there a way I can tell Haskell to partially apply all dependent functions, or is this something I have to do by hand? Also, my apologies for being imprecise with the functional programming terminology.
If you have a lot of functions that need the same parameter, and that's the only (or last) parameter they take then you can take advantage of the Monad instance for (->) r. Alternatively, you can wrap everything in the Reader monad, whose definition is basically
newtype Reader r a = Reader { runReader :: r -> a }
instance Monad (Reader r) where
return a = Reader $ \_ -> a
m >>= f = Reader $ \r -> runReader (f (runReader m r)) r
Which, compared to the Monad instance for (->) r:
instance Monad ((->) r) where
return a = const a
m >>= f = \r -> f (m r) r
How can you use this? For example, if you had a single parameter pp :: ProblemParams, then you could write functions as
-- Some declarations
smallFunc1 :: ProblemParams -> Double
smallFunc2 :: ProblemParams -> Double
smallFunc3 :: Int -> ProblemParams -> Double
doStuff :: ProblemParams -> Double -- Just a random return type
doStuff = do -- Keep the parameter implicit
result1 <- smallFunc1 -- The ProblemParams are automatically passed
result2 <- smallFunc2
result3 <- smallFunc3 10
return $ result1 + result2 + result3
And this works quite well, you just have to make sure that all of smallFunc1, smallFunc2, and smallFunc3 10 take a ProblemParams as their last parameter (notice the inclusion of 10 with smallFunc3). The Monad instance for functions will pass that parameter implicitly in all the binds. Think of it as returning a value before that value has been computed. You get to bind the "future" return value of smallFunc1 to result1.
Alternatively, you could use the Reader monad:
type Problem a = Reader ProblemParams a
reader :: (r -> a) -> Reader r a
reader f = do
r <- ask
return $ f r
-- reader f = ask >>= return . f
smallFunc1' :: Problem Double
smallFunc1' = reader smallFunc1
smallFunc2' :: Problem Double
smallFunc2' = reader smallFunc2
smallFunc3' :: Int -> Problem Double
smallFunc3' i = reader (smallFunc3 i)
doStuff :: ProblemParams -> Double
doStuff pp = flip runReader pp $ do
result1 <- smallFunc1'
result2 <- smallFunc2'
result3 <- smallFunc3' 10
return $ result1 + result2 + result3
The reason why we have to create a reader function that lifts our primitives to the Reader monad is that Reader is actually defined in terms of the transformer ReaderT as
type Reader r a = ReaderT r Identity a
around the Identity monad.
Whichever you decide to use is up to you. I think most people would be more familiar with the Reader version, and if you decided to stack on some more transformers later it'd be really simple. The Reader monad basically helps to make the function signatures look monadic, since ProblemParams -> Double doesn't look like a normal monad signature. It will use a bit more code, but it may be that it helps you reason about your program.
Note: I haven't run any of this code, so be warned that small errors may exist. If anyone spots a problem, just let me know and I'll fix it.
An example with the Par monad and ReaderT:
type App a = ReaderT ProblemParams Par a
runApp :: ProblemParams -> App a -> a
runApp pp app = runPar $ runReaderT app pp
Then you can simply use lift to raise Par actions to App actions:
parReader :: (ProblemParams -> Par a) -> App a
parReader f = do
r <- ask
lift $ f r
-- parReader f = ask >>= lift . f
doStuff :: ProblemParams -> Double
doStuff pp = runApp pp $ do
result1 <- parReader parAction1
result2 <- parReader parAction2
result3 <- parReader (parAction3 10)
return $ result1 + result2 + result3
I'm about 99% sure that the monad stack will not affect your parallelism at all, since the Reader monad executes first, essentially applying your ProblemParams to all the functions, then it runs the Par action.
i have the following set of actions:
action1 :: IO Bool
action2 :: IO Bool
action3 :: IO Bool
some actions are just composition of another actions
complexAction = do
action1
action2
action3
What i need is the construction that checks result of each action and returns False in a case of false. I can do it manually but i know for sure that haskell does have tools to get rid of that kind of boilerplate.
The simplest way is
complexAction = fmap and (sequence [action1, action2, action3])
But you could also write your own combinator to stop after the first action:
(>>/) :: Monad m => m Bool -> m Bool -> m Bool
a >>/ b = do
yes <- a
if yes then b else return False
You'd want to declare the fixity to make it associative
infixl 1 >>/
Then you can do
complexAction = action1 >>/ action2 >>/ action3
I'd suggest you to use MaybeT monad transformer instead. Using it has many advantages over just returning IO Bool:
Your actions can have different types and return values (not just true/false). If you don't need any results, just use MaybeT IO ().
Later ones can depend on results of preceding ones.
Since MaybeT produces monads that are instances of MonadPlus, you can use all monad plus operations. Namely mzero for a failed action and x mplus y, which will run y iff x fails.
A slight disadvantage is that you have to lift all IO actions to MaybeT IO. This can be solved by writing your actions as MonadIO m => ... -> m a instead of ... -> IO a.
For example:
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
-- Lift print and putStrLn
print' :: (MonadIO m, Show a) => a -> m ()
print' = liftIO . print
putStrLn' :: (MonadIO m) => String -> m ()
putStrLn' = liftIO . putStrLn
-- Add something to an argument
plus1, plus3 :: Int -> MaybeT IO Int
plus1 n = print' "+1" >> return (n + 1)
plus3 n = print' "+3" >> return (n + 3)
-- Ignore an argument and fail
justFail :: Int -> MaybeT IO a
justFail _ = mzero
-- This action just succeeds with () or fails.
complexAction :: MaybeT IO ()
complexAction = do
i <- plus1 0
justFail i -- or comment this line out <----------------<
j <- plus3 i
print' j
-- You could use this to convert your actions to MaybeT IO:
boolIOToMaybeT :: IO Bool -> MaybeT IO ()
boolIOToMaybeT x = do
r <- lift x
if r then return () else mzero
-- Or you could have even more general version that works with other
-- transformers as well:
boolIOToMaybeT' :: (MonadIO m, MonadPlus m) => IO Bool -> m ()
boolIOToMaybeT' x = do
r <- liftIO x
if r then return () else mzero
main :: IO ()
main = runMaybeT complexAction >>= print'
As Petr says, for anything but a narrow and contained case, you're almost certainly better off wiring your code for proper error handling from the outset. I know I've often regretted not doing this, condemning myself to some very tedious refactoring.
If I may, I'd like to recommend Gabriel Gonzalez's errors package, which imposes a little more coherence on Haskell's various error-handling mechanisms than has been traditional. It allows you to plumb Eithers through your code, and Either is a good type for capturing errors. (By contrast, Maybe will lose information on the error side.) Once you've installed the package, you can write things like this:
module Errors where
import Control.Error
import Data.Traversable (traverse)
data OK = OK Int deriving (Show)
action1, action2, action3 :: IO (Either String OK)
action1 = putStrLn "Running action 1" >> return (Right $ OK 1)
action2 = putStrLn "Running action 2" >> return (Right $ OK 2)
action3 = putStrLn "Running action 3" >> return (Left "Oops on 3")
runStoppingAtFirstError :: [IO (Either String OK)] -> IO (Either String [OK])
runStoppingAtFirstError = runEitherT . traverse EitherT
...with output like
*Errors> runStoppingAtFirstError [action1, action2]
Running action 1
Running action 2
Right [OK 1,OK 2]
*Errors> runStoppingAtFirstError [action1, action3, action2]
Running action 1
Running action 3
Left "Oops on 3"
(But note that the computation here stops at the first error and doesn't soldier on until the bitter end -- which might not be what you had wanted. The errors package is certainly wide-ranging enough that many other variations are possible.)