- You cannot have something named "X" theoretically does not mean you cannot have anything anyone at sometime thought to be "X". See [my answer][1] to another question for a feeling of what you can expect to get in the way of a monad *pattern* in an object oriented language. - What really concerns me is this: // liftM :: m t -> (t -> u) -> m u -- looks more similar to bind this way Why is it called `lift`? Because it takes a function in and gives a function out, but in another domain. `(t -> u) -> m t -> m u` should be read as `(t -> u) -> (m t -> m u)`, which translates to something like `Func<Func<T, U>, Func<M<T>, M<U>>>` in C#. - You should not overwrite local variables, let alone repetitively, let alone in functional-style aspirant code: game = State<Player>.Lift<GameState, GameState>(game, nextPlayerMove); game = State<Player>.Lift<GameState, GameState>(game, drawBoard); game = State<Player>.Bind<GameState, GameState>(game, findWinner); - You don't do `Monad` and `while` loop. You should use a `foldM`. - Also noticed `nextPlayerMove` may do IO. In Haskell you would not have a function interleaved with a monad, unless it is a deterministic mathematical function. For example if it used Random numbers or IO you would need a monadic transformer, see `StateT` [here][2]. In adopting functional paradigms, you should start with the low hanging fruits. Avoiding mutable state and preferring expressions over statements, etc. And look for opportunities for reification. Aim for making implicit patterns explicit (for example using applicative alternatives from IEnumerable/IQueryable instead of loops) , composability and as much compile time guarantees as possible. [1]: http://codereview.stackexchange.com/questions/20845 [2]: http://www.haskell.org/haskellwiki/Simple_StateT_use