哈斯克尔 - 也许算术

use*_*228 4 haskell functional-programming case-statement maybe

我被要求实现一个使用以下配置文件的函数:

maybe_divide :: Maybe Integer -> Maybe Integer -> Maybe Integer
Run Code Online (Sandbox Code Playgroud)

并以下列方式回应:

> maybe_divide (Just 5) (Just 2) 
Just 2
> maybe_divide (Just (-5)) (Just 2) 
Just (-3)
> maybe_divide (Just (-5)) (Just 0) 
Nothing
> maybe_divide Nothing (Just 1) 
Nothing
> maybe_divide (Just 1) Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

我写了以下但它不会编译.你们有什么建议吗?

maybe_divide :: Maybe Integer -> Maybe Integer -> Maybe Integer
maybe_divide x y = case x of
    Just x' -> case y of 
        Just y'
            | y' == 0 -> Nothing  
            | otherwise -> x' `div` y'
    Nothing -> Nothing 
Run Code Online (Sandbox Code Playgroud)

Joh*_*n L 12

与输出类型分开,我想指出一些您可能更喜欢编写此类代码的替代样式:

首先,您可以case通过将它们放在元组中来处理多个表达式:

case (x,y) of
    (_      , Just 0) -> Nothing
    (Just x', Just y') -> Just (x' `div` y')
    _ -> Nothing
Run Code Online (Sandbox Code Playgroud)

有几种不同的方法可以使用警卫甚至功能来编写它Control.Monad.guard.

case (x,y) of
  (Just x', Just y') -> (x' `div` y') <$ guard (y' /= 0)
  _ -> Nothing
Run Code Online (Sandbox Code Playgroud)

第二种方法将从一个函数开始:

safeDiv :: Integer -> Integer -> Maybe Integer
safeDiv x 0 = Nothing
safeDiv x y = Just (x `div` y)
Run Code Online (Sandbox Code Playgroud)

现在你有了safeDiv,你可以将它提升为Maybe-wrapped参数.它非常接近Applicative样式代码,除了Maybe输出中的额外层.幸运的是,嵌套的monads(例如Maybe (Maybe t))很容易崩溃:

maybe_divide x y = join $ safeDiv <$> x <*> y
Run Code Online (Sandbox Code Playgroud)

甚至

maybe_divide = (join .) . liftM2 safeDiv
Run Code Online (Sandbox Code Playgroud)

如果你能说流利的话.

就个人而言,我会使用两个元组大小写中的一个.但是已经有一个像这样的函数是相当普遍的safeDiv,在这种情况下,第二种形式可能很有用.


Phi*_* JF 7

你应该发布你得到的错误,但是

x' `div` y'
Run Code Online (Sandbox Code Playgroud)

有类型Integer而不是Maybe Integer.也许你需要把它包装成一个Just.


ham*_*mar 6

您需要将成功结果包装在Just此处:

... | otherwise -> Just (x' `div` y')
Run Code Online (Sandbox Code Playgroud)