Given the problem of dividing two numbers:
1 / 2
12 / 512
59 / -123
Seems arbitrarily easy to define a method, or even an operator, for reaching such goal. But there are hidden incumberances when applying mathematical operations with computers, especially dividing by zero.
data Expr = Val Int | Div Expr ExprThis creates a new data type Expr which could be either a Val of type Int, or Div with two Expr values.
Now, applying them would simply be
eval :: Expr -> Int
eval (Val n) = n
eval (Div x y) = eval x / eval yBut as is, it could crash the application if given y is zero.
safediv :: Int -> Int -> Maybe Int
safediv n m = if m == 0 then
Nothing
else
Just(n / m)Now with the check, it won't crash anymore when the second argument is zero.
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div n m) = case eval x of
Nothing -> Nothing
Just n -> case eval y of
Nothing -> Nothing
Just m -> safediv n / mNow abstracting the repetition (two instances of case pattern matches)
m >>= f = case m of
Nothing -> Nothing
Just x -> f xThe operator >>= will apply the function f for the argument Maybe m only if it contains a value.
eval :: Expr -> Maybe Int
eval (Val n) = return n
eval (Div n m) = eval n >>= (λx ->
eval m >>= (λy ->
safediv x y))Now, to make it simpler with the do notation
eval :: Expr -> Maybe Int
eval (Val n) = return n
eval (Div n m) = do x <- eval x
y <- eval y
safediv x yIt's the Maybe type and it can be three things:
- It may be anything, a boolean, an integer, etc
return :: a -> Maybe aThis converts a pure valueato aMaybevalue type ofa>>= :: Maybe a -> (a -> Maybe b) -> Maybe bThis takes aMaybeofa, and if possible, sequences the value tobapplying a function
- Same idea works for other effects
It may work for mutable states, I/O, capturing failures (Maybe), reading from environments. What you think of as being effects in programmings languages
- Supports pure programming with effects
It allows the creation/mutation of mutable (impure) states and effects in functions, even in pure programming languages like haskell.
- Use of effects explicit in types
When writing the operator, it explicitly typed the failure possibility (Nothing) by making it return a Maybe.
- Functions that work for any effect
For example, a sequence of functions that can have effects, and want to run them one after the other.