Skip to content

Instantly share code, notes, and snippets.

@mgrabovsky
Last active October 23, 2019 10:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgrabovsky/12b6568bccd73f5b06cfbadc4c70144c to your computer and use it in GitHub Desktop.
Save mgrabovsky/12b6568bccd73f5b06cfbadc4c70144c to your computer and use it in GitHub Desktop.
Future monad
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
data FutureM i o a
= Await (i -> FutureM i o a)
| Yield o (FutureM i o a)
| Done a
instance Functor (FutureM i o) where
fmap f (Await g) = Await (fmap f . g)
fmap f (Yield o m) = Yield o (fmap f m)
fmap f (Done a) = Done (f a)
instance Applicative (FutureM i o) where
pure = Done
Await g <*> fa = Await (\i -> g i <*> fa)
Yield o m <*> fa = Yield o (m <*> fa)
Done f <*> fa = f <$> fa
instance Monad (FutureM i o) where
Await g >>= k = Await (\i -> g i >>= k)
Yield o m >>= k = Yield o (m >>= k)
Done a >>= k = k a
class Monad (m i o) => Future m i o where
await :: m i o i
yield :: o -> m i o ()
instance Future FutureM i o where
await = Await pure
yield o = Yield o (pure ())
runFutureM :: FutureM i o a -> [i] -> (a, [o])
-- BUG: Non-total pattern match.
runFutureM (Await g) (i:ins) = runFutureM (g i) ins
runFutureM (Yield o m) ins = (o:) <$> runFutureM m ins
runFutureM (Done a) _ = (a, [])
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
data FutureM i o a
= Await (Maybe i -> FutureM i o a)
| Yield o (FutureM i o a)
| Done a
instance Functor (FutureM i o) where
fmap f (Await g) = Await (fmap f . g)
fmap f (Yield o m) = Yield o (fmap f m)
fmap f (Done a) = Done (f a)
instance Applicative (FutureM i o) where
pure = Done
Await g <*> fa = Await (\i -> g i <*> fa)
Yield o m <*> fa = Yield o (m <*> fa)
Done f <*> fa = f <$> fa
instance Monad (FutureM i o) where
Await g >>= k = Await (\i -> g i >>= k)
Yield o m >>= k = Yield o (m >>= k)
Done a >>= k = k a
class Monad (m i o) => Future m i o where
await :: m i o (Maybe i)
yield :: o -> m i o ()
instance Future FutureM i o where
await = Await pure
yield o = Yield o (pure ())
runFutureM :: FutureM i o a -> [i] -> (a, [o])
runFutureM (Await g) [] = runFutureM (g Nothing) []
runFutureM (Await g) (i:ins) = runFutureM (g $ Just i) ins
runFutureM (Yield o m) ins = (o:) <$> runFutureM m ins
runFutureM (Done a) _ = (a, [])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment