Haskell - 左箭头与嵌套的 case 语句
Haskell - Left arrow vs nested case statements
我到处找 definition/description 都没有成功。当我 Haskell 从第一原则编程 时,在 monads 介绍章节(第 763 页)中,它显示了嵌套 case 语句的示例:
mkSphericalCow :: String -> Int -> Int -> Maybe Cow
mkSphericalCow name' age' weight' =
case noEmpty name' of
Nothing -> Nothing
Just nammy ->
case noNegative age' of
Nothing -> Nothing
Just agey ->
case noNegative weight' of
Nothing -> Nothing
Just weighty ->
weightCheck
(Cow nammy agey weighty)
上面说可以替换为:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)
这到底是怎么回事!?这个叫什么?我能找到的最接近的是 this answer,它描述为“一元表示法”。
一个do
表达式被脱糖为一个>>=
函数链。 Haskell report 描述了如何对 do
表达式进行脱糖。在您的情况下,这意味着表达式被脱糖为:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = noEmpty name' >>= (\nammy -> noNegative age' >>= (\agey -> nonNegative weight' >>= (\weighty -> weightCheck (Cow nammy agey weighty))))
对于 Maybe
Monad
的实例是 implemented as [src]:
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= _ = Nothing
A Maybe
可以看作是一个可能失败的计算结果。 Nothing
是计算失败的结果,Just …
是包装在 Just
数据构造函数中的计算结果。
Monad
的实例使人们能够“链接”此类计算。这意味着它只会 return a Just …
如果所有计算都成功(return a Just …
)。所以在你的表达中:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)
所以如果函数 nonEmpty name'
、nonNegative age'
、nonNegative weight'
和 weightCheck (Cow nammy agey weighty)
returns Nothing
中的一个或多个,则整个do
块将计算为 Nothing
。 <-
箭头的左侧是 Just
展开的计算结果。这种解包是在我们看到 (Just x) >>= k = …
的 Monad
实例上完成的,其中 Just
数据构造函数因此被解包,并且 x
用作 k
函数。
这里可以这样写更方便:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = (<b>Cow <$> noEmpty name' <*> nonNegative age' <*> noNegative weight'</b>) >>= weightCheck
这里我们使用 Maybe
的 Functor
和 Applicative
实例,因此我们将生成 Maybe Cow
,即给定的 Just (Cow a b c)
Just a = noEmpty name'
、Just b = noNegative age'
、Just c = noNegative weight'
。然后我们利用 >>=
函数解包 Just
数据构造函数并将包装在 Just
中的值传递给 weightCheck
.
我到处找 definition/description 都没有成功。当我 Haskell 从第一原则编程 时,在 monads 介绍章节(第 763 页)中,它显示了嵌套 case 语句的示例:
mkSphericalCow :: String -> Int -> Int -> Maybe Cow
mkSphericalCow name' age' weight' =
case noEmpty name' of
Nothing -> Nothing
Just nammy ->
case noNegative age' of
Nothing -> Nothing
Just agey ->
case noNegative weight' of
Nothing -> Nothing
Just weighty ->
weightCheck
(Cow nammy agey weighty)
上面说可以替换为:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)
这到底是怎么回事!?这个叫什么?我能找到的最接近的是 this answer,它描述为“一元表示法”。
一个do
表达式被脱糖为一个>>=
函数链。 Haskell report 描述了如何对 do
表达式进行脱糖。在您的情况下,这意味着表达式被脱糖为:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = noEmpty name' >>= (\nammy -> noNegative age' >>= (\agey -> nonNegative weight' >>= (\weighty -> weightCheck (Cow nammy agey weighty))))
对于 Maybe
Monad
的实例是 implemented as [src]:
instance Monad Maybe where (Just x) >>= k = k x Nothing >>= _ = Nothing
A Maybe
可以看作是一个可能失败的计算结果。 Nothing
是计算失败的结果,Just …
是包装在 Just
数据构造函数中的计算结果。
Monad
的实例使人们能够“链接”此类计算。这意味着它只会 return a Just …
如果所有计算都成功(return a Just …
)。所以在你的表达中:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)
所以如果函数 nonEmpty name'
、nonNegative age'
、nonNegative weight'
和 weightCheck (Cow nammy agey weighty)
returns Nothing
中的一个或多个,则整个do
块将计算为 Nothing
。 <-
箭头的左侧是 Just
展开的计算结果。这种解包是在我们看到 (Just x) >>= k = …
的 Monad
实例上完成的,其中 Just
数据构造函数因此被解包,并且 x
用作 k
函数。
这里可以这样写更方便:
mkSphericalCow' :: String -> Int -> Int -> Maybe Cow
mkSphericalCow' name' age' weight' = (<b>Cow <$> noEmpty name' <*> nonNegative age' <*> noNegative weight'</b>) >>= weightCheck
这里我们使用 Maybe
的 Functor
和 Applicative
实例,因此我们将生成 Maybe Cow
,即给定的 Just (Cow a b c)
Just a = noEmpty name'
、Just b = noNegative age'
、Just c = noNegative weight'
。然后我们利用 >>=
函数解包 Just
数据构造函数并将包装在 Just
中的值传递给 weightCheck
.