Skip to content

Instantly share code, notes, and snippets.

@bcrisp
Last active August 31, 2016 23:44
Show Gist options
  • Save bcrisp/cf70fb5c4e325e186e2ec2463ddd247f to your computer and use it in GitHub Desktop.
Save bcrisp/cf70fb5c4e325e186e2ec2463ddd247f to your computer and use it in GitHub Desktop.
Containers as Monads

Containers as Monads

There's a common analogy of viewing Monads as containers, but what about the dual concept: utilizing containers as monads?

Docker

In Docker we can spin up containers to execute arbitrary commands using docker run. This will take a Docker image and apply the supplied commands to it; in other words, a String -> Container. Let's say I then want to apply the results of that computation and "roll" it to another container, so I need something to take a Container -> Container. With these two conditions I define a ContainerIO type to hold containers.

Caveats

  1. This only works in GHCI currently
  2. I'm using unsafePerformIO in order to implement Show

Getting started in GHCI

Lauch ghci: ghci containers.hs Execute a chain of container binds: test

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import System.Process
import Control.Monad
import Control.Monad.Trans
import System.IO.Unsafe (unsafePerformIO)
instance (Show a) => Show (ContainerIO a) where show a = show(unsafePerformIO (runHandleIO a ))
newtype ContainerIO a = ContainerIO { runHandleIO :: IO a }
deriving (Monad, MonadIO, Functor, Applicative)
data Container = Container String deriving Show
runContainer :: Container -> ContainerIO Container
runContainer (Container a) = do
b <- liftIO $ readProcess "docker" ["run", "alpine", "/bin/sh", "-c", a] ""
return $ Container b
test = runContainer (Container "echo echo echo echo") >>= runContainer >>= runContainer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment