-1

就像标题一样,代码如下:

do{ let{ the= Just "Hi!"}; _ <- sequence [the,Nothing]; pure "no way!" }

输出是Nothing。我的问题是我怎么能确定,这个 Do-block 是一个 Maybe-Monad?do语法糖的确切功能是什么?

4

1 回答 1

6

我的问题是我怎么能确定这个-blockdo是一个Maybe-Monad?

您可以执行类型推断,就像 Haskell 编译器一样。为了做到这一点,我们首先应该对 do-notation 进行脱糖,如Haskell '10 报告中所述。

你的表达相当于:

let the = Just "Hi!" in sequence [the,Nothing] >> pure "no way!"

所以现在我们知道了,让我们看看类型。很明显the是 a the :: Maybe String,所以这意味着列表[the, Nothing]具有 类型[the, Nothing] :: [Maybe String]

的类型sequencesequence :: (Traversable t, Monad m) => t (m a) -> m (t a), 所以这意味着 that tis t ~ []here 和 thatm ~ Maybea ~ Stringsuquence在此示例中,这些类型等价物具有 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 ~ Maybea ~ 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 作为语法糖的确切功能是什么?

语法糖用于使符号更方便。对于上面的例子,它可能没那么重要。对于一些较大的表达式,do会过滤掉一些噪音,因为它隐藏了>>=语句之间的运算符,而且f >>= \x -> ...写成x <- f; ...这样有时更容易跟踪哪些变量绑定到哪些表达式。

于 2019-07-17T22:40:17.280 回答