在Haskell中,如果函数返回"Maybe a"类型,那么它是安全的和完全的,它又如何有用呢?

una*_*der 1 haskell

所以我必须定义一个头函数的安全版本,当[]作为参数传递时不会抛出错误.这里是:

safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x
Run Code Online (Sandbox Code Playgroud)

但是现在,这个功能还有用吗?因为假设类型"a"是Int,那么您可以添加两个Int类型的对象,但是您不能添加两个"Maybe Int"类型的对象.

cod*_*hot 8

"Just"就是这样一个功能.以下是如何使用其结果(对于ghci REPL):

import Data.Foldable (sequenceA_)

let writeLn            = putStrLn . show

let supposedlyUnusable = writeLn <$> Just 0 
sequenceA_ supposedlyUnusable
Run Code Online (Sandbox Code Playgroud)

打印1或我们可以继续尝试另一个有趣的例子 - 使用Nothing案例

let supposedlyUnusable = writeLn <$> Nothing 
sequenceA_ supposedlyUnusable
Run Code Online (Sandbox Code Playgroud)

哪个不打印任何东西.

这是一个完整的程序,这对于其他情况下,即使工作TraversableFoldable在那里你不能这样做的一个案例分析Maybe的价值.<$>是一个关键,它允许你将函数应用于Maybe或包含在任何内容中的任何内容Functor,如果你有两个Maybe(或两个相同的Applicative),你可以使用fn <$> applicative_a <*> applicative_b类似的模式,fn a b但在哪里ab包含像Maybe值的东西.

因此,剩下几种方法可以使用Maybe我能想到的,所有这些都使用案例分析:

let {fn (Just n) = Just $ 1 + n; fn Nothing  = Nothing}
fn v
-- but that was just a messy way of writing (1+) <$> v
Run Code Online (Sandbox Code Playgroud)

...

let fn v = case v of {Just n -> Just $ 1 + n; Nothing -> Nothing}
-- and that's the same program with a different syntax
Run Code Online (Sandbox Code Playgroud)

...

import Data.Maybe (fromMaybe)
fromMaybe someDefault v
-- and that extracted the `value` from `v` if we had `Just value` or else gave us `someDefault`
Run Code Online (Sandbox Code Playgroud)

...

let {fn (Just n) = writeLn n; fn Nothing = putStrLn "No answer"}
-- this one extracts an action but also provides an action when there's nothing
-- it can be done using <$> and fromMaybe instead, but beginners tend to
-- find it easier because of the tutorials that resulted from the history
-- of the base library's development
let fn v = fromMaybe (putStrLn "No answer") (writeLn <$> v)
Run Code Online (Sandbox Code Playgroud)

哦,哦!这个是neato:

import Control.Applicative
let v = Just 0 -- or Nothing, if you want
let errorcase = pure $ putStrLn "No answer"
let successcase = writeLn <$> v
sequenceA_ $ successcase <|> errorcase
-- that uses Alternative in which Maybe tries to give an answer preferring the earliest if it can
Run Code Online (Sandbox Code Playgroud)

当然我们也有经典:

maybe (putStrLn "No answer") writeLn v
Run Code Online (Sandbox Code Playgroud)


arr*_*owd 6

正如评论中提到的那样,你实际上可以添加两个Maybe.我只是想对此提出另一种观点.

是的,你不能直接适用(+)Maybe IntS,但你可以升级到另一个功能,即能自动执行此操作.

要升级一元函数(比如(+1))你写fmap (+1) maybeInt(+1) <$> maybeInt.如果(+1)有类型Int -> Int,则fmap (+1)表达式具有类型Maybe Int -> Maybe Int.

升级bin-or-more-ary函数在语法方面要复杂一些:(+) <$> maybeInt <*> maybeInt或者liftA2 (+) maybeInt maybeInt.同样,这里我们提倡(+) :: Int -> Int -> IntliftA2 (+) :: Maybe Int -> Maybe Int -> Maybe Int.

Maybe以这种方式处理允许您构建一个与Maybe纯函数中的s 一起使用并推迟检查的计算Nothing.或者甚至避免这种情况,如果你最终将它插入另一个Maybe作为参数的函数.

当然,你可以使用fmap和使用liftA任何Applicative,而不仅仅是Maybe.