factored out the match monad into a simpler module