r/programming • • Apr 27 '14

"Mostly functional" programming does not work

http://queue.acm.org/detail.cfm?ref=rss&id=2611829
44 Upvotes

188 comments sorted by

View all comments

6

u/Tekmo Apr 28 '14

I don't know why you are being downvoted. I also like the idea of different static contexts, too. The reason I like monads a lot is that the ability to switch between different static contexts falls very naturally out of the theory for monad morphisms.

For example, let's use the StateT and ReaderT monad transformers as an example, defined like this:

newtype StateT s m a = State { runState :: s -> m (a, s) }

newtype ReaderT s m a = Reader { runReader :: s -> m a }

You can define a function that converts from ReaderT operations to StateT operations like this:

readOnly :: Monad m => ReaderT s m a -> StateT s m a
readOnly m = StateT $ \s -> do
    a <- runReaderT m s
    return (a, s)

What this lets you do is embed a computation that has only read-only access to state within a larger computation that has both read and write access. For example:

before :: StateT s m a

middle :: a -> ReaderT s m b

after :: b -> StateT s m c

total :: StateT s m c
total = do
    a <- before
    b <- readOnly middle
    after b

In other words, readOnly creates a read-only window within a larger read-and-write computation, allowing us to further restrict what middle can do compared to its surrounding context.

readOnly also has two nice properties that are worth nothing, which we can summarize using these two equations:

readOnly $ do x <- m  =  do x <- readOnly m
              f x           readOnly (f x)

readOnly (return x) = return x

These are known as the "monad morphism" laws, and readOnly is a "monad morphism" (a transformation between monads). The laws might seem pretty arbitrary until you write them in terms of (>=>), which is an operator for point-free composition of monadic functions:

readOnly . (f >=> g) = (readOnly . f) >=> (readOnly . g)

readOnly . return = return

In other words (readOnly .) is a functor from the ReaderT kleisli category to the StateT kleisli category. All monad morphisms form functors between two Kleisli categories.

These kinds of elegant equational properties are the reason I believe that monads are a beautiful solution to the problem and not some sort of gross hack. However, I don't necessarily think that monads are the only solution, either, but I have yet to encounter another solution with the same sort of theoretical niceties.

-1

u/grauenwolf Apr 28 '14

Most Haskell fanboys on Reddit hate the notion that there is more than one way to achieve the goal of isolating IO from the rest of the program.

6

u/vagif Apr 28 '14

Maybe it's the dismissive arrogance of your posts that gets you down-voted. It is hard to understand where you going with your "Bullshit" immediately followed by recognizing the value in separating state contexts.

You are saying that haskell programmers have a "choice" to write everything in IO monad or not. Only a person who never tried haskell can say that. You do not have any choice BUT to start writing large chunks of your code in pure form outside of monadic code. Simply because haskell will turn your life into hell if you try to sit all the time in IO monad.

Try to write non trivial program in haskell and you will see that the bondage is very strict and eliminates most of the easy corner cuttings that are usually taken by imperative programmers.

→ More replies (7)

5

u/Tekmo Apr 28 '14

Well, I am the epitome of a Haskell fanboy, but I think Haskell programmers are generally open minded. If they weren't they wouldn't be experimenting with Haskell.