Wil*_*sco 1 monads haskell functor maybe
我可以看到这里有很多关于 Maybe 类型和构图的问题,但我很困惑,如果我很诚实的话,阅读这些会让我头疼。
这是我的情况:
举例来说,我有一个函数:
addm a b = Just (a + b)
Run Code Online (Sandbox Code Playgroud)
如何add :: Maybe Int -> Maybe Int -> Maybe Int
使用addm
函数创建函数而不使用模式匹配来解包Maybe
s?
我试过类似的东西
add x y = (addm <$> x) <*> y
Run Code Online (Sandbox Code Playgroud)
但这有一种 Maybe Int -> Maybe Int -> Maybe (Maybe Int)
如果可能的话,我还想避免使用标准库之外的任何东西。
编辑:在我的具体情况下,我实际上只需要一个函数,Maybe Int -> Int -> Maybe Int
所以我能够使用
add x y = x >>= addm y
Run Code Online (Sandbox Code Playgroud)
成功了。不过,我仍然对原始问题的答案感到好奇。
有很多方法可以写这个。所有都涉及到Maybe
一个 Monad的事实。
也许最容易理解的方法是使用join函数,对于任何 Monad,它都会删除最外层的嵌套。这里有 type Maybe (Maybe a) -> Maybe a
,这正是您要寻找的,与标准 Applicative 运算符相结合:
add ma mb = join $ addm <$> ma <*> mb
Run Code Online (Sandbox Code Playgroud)
或者您可以使用do
符号以更命令式的方式编写计算,看起来像变量赋值,其中 Monad 负责传播任何Nothing
值:
add ma mb = do
a <- ma
b <- mb
addm a b
Run Code Online (Sandbox Code Playgroud)
或者,您可以显式使用“绑定”( >>=
) 运算符,这就是do
上面的代码块的作用(但我发现这比其他两个选项更不明确和易于理解):
add ma mb = ma >>= \a -> mb >>= \b -> addm a b
Run Code Online (Sandbox Code Playgroud)
join
在上面贴一个。
Control.Monad.join :: Monad m => m (m a) -> m a -- combine two ms into one, this is why, as the meme goes, monads are monoids in the category of endofunctors
add x y = join $ addm <$> x <*> y
Run Code Online (Sandbox Code Playgroud)
我想指出,addm
这样的写法(实际上,任何总是返回的函数Just
)都是不自然的。您实际上只需编写add x y = (+) <$> x <*> y
或 只是,但是当您处理真正有趣的单子代码时,以应用风格add = liftA2 (+)
抛出在表达式之上的一般模式非常有用。join