0

如果我们选择它们作为 的数据类型,monadPlusSDif这两个函数是否等效?MaybeMonadPlus

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)
4

2 回答 2

9

好吧MaybeMonadPlus例如

instance MonadPlus Maybe where
  mempty = Nothing

guard实现为

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

有了这些知识,您可以使用等式推理来推断,当mis时Maybe,您可以替换原始代码

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

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

或者

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

或者

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

或者

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

所以你看到功能是相同的。

于 2014-01-24T17:26:55.480 回答
5

如果 ,这些函数将具有等效的行为m ~ Maybe,但它们编译的字节码表示可能会有所不同。你也可以用一般MonadPlus单子的实际守卫来实现它

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

然后你可以用它作为

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

并且编译器将能够弄清楚在这种情况下,它应该使用Maybefor m

于 2014-01-24T17:24:09.960 回答