Question

Are both functions equivalent if we choose them at monadPlusSDif, Maybe as the data type for MonadPlus?

tdif :: Int -> Int -> Maybe Int
tdif x y
    | y == 0 = Nothing
    | otherwise = Just (div x y)

monadPlusSDif :: MonadPlus m => Int -> Int -> m Int
monadPlusSDif x y = guard (y /= 0) >> return (div x y)
Was it helpful?

Solution 2

These functions will have equivalent behavior if m ~ Maybe, but their compiled byte-code representation will likely be different. You could also implement it with actual guards for general MonadPlus monads as

monadPlusSDif :: MonadPlus m => Int -> Int -> m Int
monadPlusSDif x y
    | y == 0 = mzero
    | otherwise = return $ x `div` y

Then you could use it as

bigEquation :: Int -> Int -> Maybe Int
bigEquation x y = do
    z1 <- monadPlusSDif x y
    z2 <- monadPlusSDif (x + y) (x - y)
    z3 <- monadPlusSDif y x
    return $ z1 + z2 * z3

and the compiler would be able to figure out that in that context, it should use Maybe for m.

OTHER TIPS

Well, for Maybe the MonadPlus instance is

instance MonadPlus Maybe where
  mempty = Nothing

and guard is implemented as

guard b = if b then return () else mempty
--      = if b then Just   () else Nothing

With that knowledge, you can use equational reasoning to deduce that, when m is Maybe, you can replace the original code

monadPlusSDif x y = guard (y /= 0) >> return (div x y)

with

monadPlusSDif x y = (if y /= 0
  then Just ()
  else Nothing) >> Just (div x y)

or

monadPlusSDif x y
  | y /= 0    = Just () >>= \_ -> Just (div x y)
  | otherwise = Nothing >>= \_ -> Just (div x y)

or

monadPlusSDif x y
  | y /= 0    = Just (div x y)
  | otherwise = Nothing

or

monadPlusSDif x y
  | y == 0    = Nothing
  | otherwise = Just (div x y)

so you see that the functions are identical.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top