更改使用模式匹配来应用绑定运算符的do表达式

问题描述 投票:2回答:1

[LYAH, in For a Few Monads More显示此功能,

solveRPN :: String -> Maybe Double  
solveRPN st = do  
    [result] <- foldM foldingFunction [] (words st)  
    return result

将模式匹配与do表达式结合使用以确保从foldM出来的单子包装单个列表]

为了真正理解do表达式以及Monad的本质,我一直在用>>=>>而不是do表达式重写那本书中的大多数示例Real World Haskell中也有人建议使用,但我不记得是哪一章。

关于上面的功能,我有点困惑。不使用do表达式编写代码的最简洁方法是什么?我能想到的最好的是

solveRPN :: String -> Maybe Double
solveRPN s = foldM step [] (words s) >>= \x -> case x of
                                               [y] -> Just y
                                               _   -> Nothing

但是我希望有一种更干净的东西,因为这有两个原因,所以很吵:

  • 它使用lambda
  • 它使用case表达式,看起来比if-then-else更好。

[This question与当前版本有关。

haskell monads
1个回答
1
投票

Haskell报表中指定的desugaring of do notation实际上包括模式匹配,以便处理现在与do类型类一起指定的fail的模式匹配失败。它可以写为MonadFail或功能。

case

因此在您的示例中,可能看起来像这样。

do {e}                 =  e
do {e;stmts}           =  e >> do {stmts}
do {p <- e; stmts}     =  let ok p = do {stmts}
                              ok _ = fail "..."
                            in e >>= ok
do {let decls; stmts}  =  let decls in do {stmts}

(当然solveRPN :: String -> Maybe Double solveRPN st = foldM foldingFunction [] (words st) >>= \ x -> case x of [result] -> return result _ -> fail "Pattern match failure in do expression at file:line:col" 只是fail message :: Maybe a。]

您可以使用Nothing使其更加简洁,以避免多余的变量。]​​>

LambdaCase

这是标准的减重法,但是如果您想进一步打高尔夫球,可以使用辅助功能。如果要允许非单个列表,则标准{-# LANGUAGE LambdaCase #-} solveRPN :: String -> Maybe Double solveRPN st = foldM foldingFunction [] (words st) >>= \ case [result] -> return result _ -> fail "Pattern match failure in do expression at file:line:col" 有效。

listToMaybe :: [a] -> Maybe a

没有标准import Data.Maybe (listToMaybe) solveRPN :: String -> Maybe Double solveRPN st = foldM foldingFunction [] (words st) >>= listToMaybe ,但您可以轻松编写一个。

singletonToMaybe

然后使用单子合成运算符singletonToMaybe :: [a] -> Maybe a singletonToMaybe [x] = Just x singletonToMaybe _ = Nothing -- or: singletonToMaybe xs = guard (isSingleton xs) *> listToMaybe xs isSingleton = null . drop 1 <=<以无点样式编写该函数。

>=>    
© www.soinside.com 2019 - 2024. All rights reserved.