簡體   English   中英

內部Haskell Monads

[英]Inside Haskell Monads

我有以下代碼可以編譯並運行良好。 我試圖通過用case scanEmployee p of替換case newEmployee of來使其更緊湊,但是它不起作用。 從代碼中刪除newEmployee (和newTeam )可能是一種簡單的方法,對嗎?

module Main( main ) where
import Control.Monad.State

data Employee  = EmployeeSW  Int Int | EmployeeHW Int String deriving ( Show )
data Employee' = EmployeeSW'     Int | EmployeeHW'    String deriving ( Show )

scanTeam :: [Employee] -> State (Int,Int) (Either String [Employee'])
scanTeam [    ] = return (Right [])
scanTeam (p:ps) = do
    newEmployee <- scanEmployee p
    case newEmployee of
        Left errorMsg -> return (Left errorMsg)
        Right e -> do
            newTeam <- scanTeam ps
            case newTeam of
                Right n -> return (Right (e:n))
                Left errorMsg -> return (Left errorMsg)

scanEmployee :: Employee -> State (Int,Int) (Either String Employee')
-- actual code for scanEmployee omitted ...

您可以使用LambdaCase並使用>>=進行顯式表示,而不要使用do塊。 結果不會短很多:

scanEmployee p >>= \case
    Left errorMsg -> return (Left errorMsg)
    Right e       -> do ...

您可以使用mapMsequence來簡化代碼:

mapM scanEmployee :: [Employee] -> State (Int, Int) [Either String Employee')

sequence :: [ Either String a ] -> Either String [ a ]

(請注意,這些類型簽名是簡化的,實際類型更通用。具體而言, mapMsequence適用於任何monad(不僅是Either String )和任何可遍歷的(不僅是([]) ))

並編寫一個簡單的解決方案:

scanTeam = fmap sequence . mapM scanEmployee

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM