# Haskell: Laziness, Type Class, and Monad

## Laziness #

A function is strict in an argument if the result is undefined whenever an undefined value is passed to this argument. For instance, `(+)` is strict in both arguments, while (&&) is strict in its first only. Recall that it is defined by

``````True && x = x
False && x = False
``````

...

If a function is not strict in an argument, we say that it is non-strict or lazy in that argument.

-- Haskell: The Craft of Function Programming (3e):517

### Infinite List #

``````fibs ::[Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
take 3 fibs
``````

### Mutual Recursion #

Unlike OCaml, mutual recursion in Haskell does not need to use `let rec` (because of laziness).

``````isEven :: Int -> Bool
isEven 0 = True
isEven n = isOdd (n - 1)

isOdd :: Int -> Bool
isOdd 0 = False
isOdd n = isEven (n - 1)
``````

## Type Class #

``````quickSort :: Ord a => [a] -> [a]

quickSort []     = []
quickSort (x:xs) = quickSort [e|e<-xs,e<=x] ++ [x] ++ quickSort [e|e<-xs, e>x]
``````

`Ord` is a type class (interface), and `[e|e<-xs,e<=x]` is list comprehension.

Function signatures defined in type class are similar to overloading in other languages.

``````class Eq a where
(==) :: a -> a -> Bool
``````

`instance` of type class is similar to classes implemented interface in other languages.

``````instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f  = f x
fail _ = Nothing
``````

But what is Monad? Read on.

## Monad #

Monad is like a box. It keeps tracking of some extra content and makes code cleaner (but not necessary clearer).

### Maybe Monad #

The Maybe monad chains (`>>=`) sequences of operations and hides failure handling (extra context) in a monad.

Let's revisit the definition of Maybe from this perspective: (`--` starts a comment in Haskell)

``````instance Monad Maybe where
-- `return` is a function to wrap x as `Just x`.
return x = Just x
-- As soon as one fails, the rest are ignored and the final result is `Nothing`.
Nothing >>= f = Nothing
-- Only apply `f` when x is `Just x`， not `Nothing`.
Just x >>= f  = f x
-- Throw a failure.
fail _ = Nothing
``````

### Monadic Classes #

The type class of Monad is defined as below:

``````class Monad m where
-- core functions of Monad
(>>=)  :: m a -> (a -> m b) -> m b
return :: a -> m a

-- other functions
(>>)   :: m a -> m b -> m b
m >> k = m >>= \_ -> k -- `\_ -> k` is a lambda

fail   :: String -> m a
fail s = error s
``````

`fail` is like `throw` in other languages. Haskell uses it to in pattern matching to enable failure. We do not write them explicitly in code.

`>>` is a syntax sugar to throw away the result of `m a`. Thus `putStr "foo" >== \_ -> putStr "bar"` can be expressed as `putStr "foo" >> putStr "bar"`.

`>>=` chains tow computations, passing the result of the first computation to the second computation, by wrapping the second computation in a function, and passing the first result as its parameter.

Unlike other languages, in Haskell, `return` wraps date in a monad.

Let's revisit the definition of Maybe monad under the perspective of monadic class.

``````instance Monad Maybe where
return :: a -> Maybe a
return x = Just x
>>= :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= f = Nothing
Just x >>= f  = f x
fail :: String -> Maybe a
fail _ = Nothing
``````

### Do Notation #

``````helloWorld :: IO ()
helloWorld =
do
putStr "Hello"
putStr " "
putStrLn "world!"
``````

Haskell syntax is layout sensitive, in other words, it conforms to offside rule. Although Haskell does support braces and semicolons, this alternative style is rare in the Haskell community.

``````do { putStr "Hello"; putStr " "; putStrLn "world!"; }
``````

Within a do notation, `<-` binds the result to a name.

``````echo :: IO ()
echo =
do
line <- getLine
putStrLn line
``````

In fact, do notation is an alternative syntax for monad:

``````putStr "Hello" >> putStr " " >> putStrLn "world!"

echo :: IO ()
echo = getLine >>= putStrLn
``````