首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用镜头读取多个字段

使用镜头读取多个字段
EN

Stack Overflow用户
提问于 2014-11-04 04:19:26
回答 1查看 2.1K关注 0票数 21

给定的类型

代码语言:javascript
复制
data Prisoner = P { _name   :: String
                  , _rank   :: Int
                  , _cereal :: Cereal }

data Cereal = C { _number             :: Int
                , _percentDailyValue  :: Map String Float
                , _mascot             :: String }

我可以通过模式匹配来提取某人的姓名、等级和麦片编号:

代码语言:javascript
复制
getNameRankAndCerealNumber_0 :: Prisoner -> (String, Int, Int)
getNameRankAndCerealNumber_0 (P { _name=name
                                , _rank=rank
                                , _cereal = C { _number=cerealNumber }}
                             ) = (name, rank, cerealNumber)

或者,我可以使用镜头来分别提取每个部分。

代码语言:javascript
复制
makeLenses ''Cereal
makeLenses ''Prisoner

getNameRankAndCerealNumber_1 :: Prisoner -> (String, Int, Int)
getNameRankAndCerealNumber_1 p = (p ^. name, p ^. rank, p ^. cereal.number)

有没有一种方法可以在一次数据结构遍历中同时提取这三种数据?

结合使用GetterGetter s a -> Getter s b -> Getter s (a,b)

EN

回答 1

Stack Overflow用户

发布于 2014-11-07 11:17:33

充实了danidiaz's answer above,我能够使用ReifiedGetter构造一个Getter Prisoner (String, Int, Int)

代码语言:javascript
复制
getNameRankAndCerealNumber_2 :: Prisoner -> (String, Int, Int)
getNameRankAndCerealNumber_2 = p ^. nameRankAndCerealNumber_2

nameRankAndCerealNumber_2 :: Getter Prisoner (String, Int, Int)
nameRankAndCerealNumber_2 = runGetter ((,,) <$> Getter name <*> Getter rank <*> Getter (cereal.number))

和一个使用alongsideLens' Prisoner (String, Int, Int),尽管我必须在PrisonerHList [String, Int, Int]之间以及HList [a,b,c](a,b,c)之间手动构建Iso'

代码语言:javascript
复制
getNameRankAndCerealNumber_3 :: Prisoner -> (String, Int, Int)
getNameRankAndCerealNumber_3 p = p ^. nameRankAndCerealNumber_3

setNameRankAndCerealNumber_3 :: (String, Int, Int) -> Prisoner -> Prisoner
setNameRankAndCerealNumber_3 t p = p & nameRankAndCerealNumber_3 .~ t

nameRankAndCerealNumber_3 :: Lens' Prisoner (String, Int, Int)
nameRankAndCerealNumber_3 = hlist . alongside id (alongside id number) . triple
  where triple :: Iso' (a,(b,c)) (a,b,c)
        triple = dimap (\(a,(b,c)) -> (a,b,c)) (fmap $ \(a,b,c) -> (a,(b,c)))
        hlist :: Iso' Prisoner (String, (Int, Cereal))
        hlist = dimap (\(P n r c) -> (n,(r,c))) (fmap $ \(n,(r,c)) -> P n r c)

也许有一种更简单的方法可以做到这一点,但这是另一个问题。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26722458

复制
相关文章

相似问题

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