就像标题一样,代码如下:
do{ let{ the= Just "Hi!"}; _ <- sequence [the,Nothing]; pure "no way!" }
输出为Nothing。我的问题是如何确定这个Do-block是Maybe-Monad?do作为语法糖的确切功能是什么?
我的问题是如何确定-block
do是Maybe-Monad?
您可以执行类型推断,就像Haskell编译器一样。为了做到这一点,我们首先应该像在Haskell '10报告中所描述的那样去糖化 do-notation 。
您的表达等效于:
let the = Just "Hi!" in sequence [the,Nothing] >> pure "no way!"
Run Code Online (Sandbox Code Playgroud)
现在我们知道了,让我们看一下类型。显然,这the是一个the :: Maybe String,因此意味着列表[the, Nothing]具有type [the, Nothing] :: [Maybe String]。
该类型的sequence是sequence :: (Traversable t, Monad m) => t (m a) -> m (t a),这样就意味着t是t ~ []在这里,而且m ~ Maybe和a ~ String。在这些suquence示例中,具有这些类型的等效项为type sequence :: [Maybe String] -> Maybe [String]。因此,这意味着sequence [the, Nothing]具有类型sequence [the, Nothing] :: Maybe [String]。
该(>>)函数具有类型Monad m => m a -> m b -> m b。由于的左操作数>>具有类型,Maybe [String]因此这意味着m ~ Maybeand a ~ String。正确的操作数是pure“没办法!”。pure具有类型pure :: Applicative f => a -> f a。我们可以推导出a ~ String在这里,由于右操作数需要有类型m b从(>>)功能类型,因此,这意味着m b ~ f a,从而获得一种f ~ Maybe。
因此,我们可以得出的类型(>>) (sequence [the, Nothing]) (pure "No way!")为Maybe String。
做为语法糖到底有什么功能?
语法糖用于使符号更方便。对于上面的示例,这可能没什么大不了的。对于某些较大的表达式,do将滤除一些杂音,因为它>>=在语句之间隐藏了运算符,此外,f >>= \x -> ...编写为x <- f; ...,这样有时可以更轻松地跟踪将变量绑定到哪些表达式。