I have the following code that compiles and runs fine. I tried to make it more compact by replacing case newEmployee of
with case scanEmployee p of
, but it didn't work. There's probably an easy way to remove newEmployee
(and newTeam
) from the code right?
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 ...
You could use LambdaCase
and be explicit with >>=
instead of using do
blocks. The result is not much shorter:
scanEmployee p >>= \case
Left errorMsg -> return (Left errorMsg)
Right e -> do ...
You can simplify your code a bit with mapM
and sequence
:
mapM scanEmployee :: [Employee] -> State (Int, Int) [Either String Employee')
sequence :: [ Either String a ] -> Either String [ a ]
(Note that these type signatures are simplifications and the actual types are more general. Specifically mapM
and sequence
work for any monad (not just Either String
) and any traversable (not just ([])
))
And write a simple solution:
scanTeam = fmap sequence . mapM scanEmployee
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.