[英]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 ...
您可以使用mapM
和sequence
來簡化代碼:
mapM scanEmployee :: [Employee] -> State (Int, Int) [Either String Employee')
sequence :: [ Either String a ] -> Either String [ a ]
(請注意,這些類型簽名是簡化的,實際類型更通用。具體而言, mapM
和sequence
適用於任何monad(不僅是Either String
)和任何可遍歷的(不僅是([])
))
並編寫一個簡單的解決方案:
scanTeam = fmap sequence . mapM scanEmployee
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.