首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell Monads内部

Haskell Monads内部
EN

Stack Overflow用户
提问于 2019-03-04 03:26:18
回答 2查看 111关注 0票数 0

我有以下代码,可以很好地编译和运行。我试图通过用case scanEmployee p of替换case newEmployee of来使它更紧凑,但它不起作用。可能有一种简单的方法可以从代码中删除newEmployee (和newTeam),对吧?

代码语言:javascript
复制
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 ...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-04 03:55:21

您可以使用mapMsequence来简化代码

代码语言:javascript
复制
mapM scanEmployee :: [Employee] -> State (Int, Int) [Either String Employee')

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

(请注意,这些类型签名是简化的,实际的类型更通用。具体来说,mapMsequence适用于任何monad (不仅仅是Either String)和任何可遍历的(不仅仅是([])))

然后写一个简单的解决方案:

代码语言:javascript
复制
scanTeam = fmap sequence . mapM scanEmployee
票数 2
EN

Stack Overflow用户

发布于 2019-03-04 03:43:29

您可以使用LambdaCase和显式的>>=,而不是使用do块。结果并不是很短:

代码语言:javascript
复制
scanEmployee p >>= \case
    Left errorMsg -> return (Left errorMsg)
    Right e       -> do ...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54972798

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档