While in examining binding article, we start from bind operator, then convert it to do notation. This article start from do, and revert it back to monadic code using a few operator.
I also add Kleiski Fish Operator, that is very useful as a shortcut in a do notation.
This tutorial/ guidance/ article is one of some parts.
References: About Monad.
Examining Bind: Bind
>>=operator. Hello World Example.
<$>operators. Personal Notes. Example using Number.
Monadic Operator: Fish
The first one is overview, then some references. The last three parts is all about Example Code.
I you need to know more about operator,
you can just ask
And if you are curious for another operator, you can read this article and have fun.
then >> operator
bind >>= operator can be found here.
Think Function in Haskell as Math Equation
Suppose we have this very short function.
greetingFunction :: String greetingFunction = "Hello " ++ "World" main = do putStrLn greetingFunction
Think Action in Haskell as Procedure, Sequence of Command
We can rewrite this as an action
greetingAction :: IO () greetingAction = do putStr "Hello " putStr "World" putStrLn "" main = do greetingAction
do special notation,
we can desugar the
then >> operator as below.
greetingAction :: IO () greetingAction = putStr "Hello " >> putStr "World" >> putStrLn ""
Writing it oneliner, would make this action looks exactly like a function. And in fact, it is just a function.
greetingAction = putStr "Hello " >> putStr "World" >> putStrLn ""
then >> operator is
bind >>= operator,
except it ignore input.
We need other example containing input.
do notation does avoid coding horror,
but sooner or later we need to know what is inside.
Consider this action.
Each command has a
Maybe String result type.
import Data.Maybe greetingStr :: Maybe String greetingStr = do str1 <- Just "Hello " str2 <- Just "World" Just (str1 ++ str2) main = putStrLn $ fromMaybe "Nothing" greetingStr
We can desugar the action above
into vanilla monadic code without
greetingStr :: Maybe String greetingStr = Just "Hello " >>= \str1 -> Just "World" >>= \str2 -> Just (str1 ++ str2)
Or you can make it oneliner vanilla monadic code.
greetingStr = Just "Hello " >>= \str1 -> Just "World" >>= \str2 -> Just (str1 ++ str2)
Here is another IO example, showing you home directory.
import System.Directory main = getHomeDirectory >>= putStrLn
There is also good example here
Operation inside Bind
Monads is way to unwrap stuff, do something about it, and wrap the result. Or better, Monad give access for method, to work inside wrapped stuff, without unwrapping it.
This list, will show Monad is overloaded for different types. Every monad has its own implementation.
intList :: [Int] intList = do x <- [3..5] [x*2]
main = putStrLn $ show intList
This will display
It can be desugared into oneliner vanilla monadic code.
intList = [3..5] >>= \x -> [x*2]
The Monad Class
It is clear that sequence command in do notation is
just functions chained together
bind >>= operator
then >> operator.
Now the next question. What is these two operators has to do with monad ? So here it is the definition of monad in Prelude 220.127.116.11
class Applicative m => Monad m where (>>=) :: forall a b. m a -> (a -> m b) -> m b (>>) :: forall a b. m a -> m b -> m b m >> k = m >>= \_ -> k return :: a -> m a return = pure fail :: String -> m a fail s = errorWithoutStackTrace s
Those two are Monad Operators.
What other practical used, Monads are good for?
There are many I guess. One of them is Kleiski Arrow.
Kleiski Arrow does function composition, just like
except it perform monadic effects.
Reference about Kleiski Arrow
<=< operator can be found here.
I looks like fish, so we can call this
Consider this function
greetStr :: String -> String greetStr text = "Hello " ++ text
We can avoid closing bracket
function application $.
main = putStrLn $ greetStr "World"
Or we can join two function
function composition ..
main = (putStrLn . greetStr) "World"
Consider this action
greetStrIO :: String -> IO String greetStrIO text = return ("Hello " ++ text)
Since the output is
IO String, while expected input type
The composition have to be Monadic. Kleiski Arrow perform this well.
import Control.Monad main = (putStrLn <=< greetStrIO) "World"
Or Kleisli Composition, using reversed arrow.
import Control.Monad main = (greetStrIO >=> putStrLn) "World"
Thank you for Reading.
We shall meet again.