如果我们在monadPlusSDif
,Maybe
选择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)
的数据类型,它们是否等效?
{{1}}
答案 0 :(得分:9)
好吧,对于Maybe
,MonadPlus
实例是
instance MonadPlus Maybe where
mempty = Nothing
和guard
实现为
guard b = if b then return () else mempty
-- = if b then Just () else Nothing
有了这些知识,您可以使用等式推理来推断,当m
为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)
所以你看到功能是相同的。
答案 1 :(得分:5)
如果m ~ Maybe
,这些函数将具有等效行为,但它们的编译字节代码表示可能会有所不同。你也可以用普通MonadPlus
monad的实际守卫来实现它
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
并且编译器能够在该上下文中找出它应该Maybe
使用m
。