Pergunta

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)
Foi útil?

Solução 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.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top