A , we addressed some important steps to advance past the “beginner” stage of Haskell. We learned how to organize your project and how to find the relevant documentation. This week we’re going to continue to look at another place where we can make a big step up. We’ll explore how to expand our vocabulary on monad usage. few weeks ago Monads are a vital component of Haskell. You can’t use a lot of libraries unless you know how to incorporate their monadic functions. These functions often involve a monad that is custom to that library. When you’re first starting out, it can be hard to know how to incorporate these monads into the rest of your program. In this article, we’ll focus on a specific pattern a lot of monads and libraries use. I call this pattern the “run” pattern. Often, you’ll use a function with a name like or , where is the name of the monad. These functions will always take a monadic expression as their first argument. Then they'll also take some other initialization information, and finally return some output. This output can either be in pure form or a different monad you’re already using like . We’ll start by seeing how this works with the monad, and then move onto some other libraries. runXXX runXXXT XXX IO State Once you grasp this topic, it seems very simple. But a lot of us first learned monads with a bad mental model. For instance, the first thing I learned about monads was that they had side effects. And thus, you can only call them from places that have the same side effects. This applies to IO but doesn’t generalize to other monads. So even though it seems obvious now, I struggled to learn this idea at first. But let’s start looking at some examples of this pattern. For a more in depth look at monads, check out our series on ! We start by learning about simpler things like functors. Then we eventually work our way up to monads and even monad transformers! Functional Data Structures The Basics of “Run”: The State Monad Let’s start by recalling the monad. This monad has a single type parameter, and we can access this type as a global read/write state. Here’s an example function written in the monad: State State stateExample :: State Int (Int, Int, Int)stateExample = do a <- get modify (+1) b <- get put 5 c <- get return (a, b, c) If this function is confusing, you should take a look at the . It’ll at least show you the relevant type signatures. First we read the initial state. Then we modify it with some function. Finally we completely change it. documentation for [State](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html) In the example above, if our initial state is 1, we’ll return as the result. If the initial state is 2, we’ll return . But suppose we have a pure function. How do we call our state function? (1,2,5) (2,3,5) pureFunction :: Int -> IntpureFunction = ??? The answer is the function. We can check the documentation and find its type: runState runState :: State s a -> s -> (a, s) This function has two parameters. The first is a action. We’ll pass our function above as this parameter! Then the second is the initial state, and this is how we’ll configure it. Then the result is pure. It contains our result, as well as the final value of the state. So here’s a sample call we can make that gives us this monadic expression in our pure function. We’ll call it from a clause, and discard the final state: State where pureFunction :: Int -> IntpureFunction input = a + b + c where ((a,b,c), _) = runState stateExample input This is the simplest example of how we can use the pattern. runXXX Upgrading to Transformers Now, suppose our function isn’t quite pure. It now wants to print some of its output, so it’ll need the monad. This means it’ll use the monad transformer over : State IO StateT IO stateTExample :: StateT Int IO (Int, Int, Int)stateTExample = do a <- get lift $ print “Initial Value:” lift $ print a modify (+1) b <- get lift $ putStrLn “After adding 1:” lift $ print b put 5 c <- get lift $ putStrLn “After setting as 5:” lift $ print c return (a, b, c) Now instead of calling this function from a pure format, we’ll need to call it from an function. But once again, we’ll use a function. Now though, since we’re using a monad transformer, we won’t get a pure result. Instead, we’ll get our result in the underlying monad. This means we can call this function from . So let’s examine the type of the function. We’ve substituted for the generic monad parameter : IO runXXX IO runStateT IO m runStateT :: StateT s IO a -> s -> IO (a, s) It looks a lot like , except for the extra parameters! Instead of returning a pure tuple for the result, it returns an action containing that result. Thus we can call it from the monad. runState IO IO IO main :: IO ()main = do putStrLn “Please enter a number.” input <- read <$> getLine results <- runStateT stateTExample input print results We’ll get the following output as a result: Please enter a number.10Initial Value:10After adding 111After setting as 55(10, 11, 5) Using “run” for Libraries This pattern will often extend into libraries you use. For example, in our , we examine the library. A lot of the individual parser combinators in that library exist in the or monad. So we can combine a bunch of different parsers together into one function. series on parsing Megaparsec Parsec ParsecT But then to run that function from your normal code (or another monad), you need to use the function. Let’s look at its type signature: IO runParserT runParserT :: Monad m -> ParsecT e s m a -> String -- Name of source file -> s -- Input for parser -> m (Either (ParseError (Token s) e) a) There are a lot of type parameters there that you don’t need to understand. But the structure is the same. The first parameter to our function is the monadic action. Then we’ll supply some other inputs we need. Then we get some result, wrapped in an outer monad (such as ). run IO We can see the same pattern if we use the library to make client-side API calls. Any call you make to your API will be in the monad. Now here’s the type signature of the function: servant-client ClientM runClientM runClientM :: ClientM a -> ClientEnv -> IO (Either ServantError a) So again, the same pattern emerges. We’ll compose our monadic action and pass that as the first parameter. Then we’ll provide some initial state, in this case a . Finally, we’ll get our result ( ) wrapped in an outer monad ( ). ClientEnv Either ServantError a IO Monads within Expressions It’s also important to remember that a lot of basic monads work without even needing a function! For instance, you can use a or monad to take out some of your error handling logic: runXXX Maybe Either divideIfEven :: Int -> Maybe IntdivideIfEven x = if x `mod` 2 == 0 then Just (x `quot` 2) else Nothing dividesBy8 :: Int -> BooldividesBy8 = case thirdResult of Just _ -> True Nothing -> False where thirdResult :: Maybe Int thirdResult = do y <- divideIfEven x z <- divideIfEven y divideIfEven z Conclusion Monads are the key to using a lot of different Haskell libraries. But when you’re first starting out, it can be very confusing how you call into these functions from your code. The same applies with some common monad transformers like and . The most common pattern to look out for is the pattern. Master this pattern and you’re well on your to understanding monads and writing better Haskell! Reader State runXXXT For a closer look at monads and similar structures, make sure to read our series on . If the code in this article was confusing, you should definitely check it out! And if you’ve never written Haskell but want to start, download our ! Functional Data Structures Beginners Checklist