如何修改嵌套自定义数据类型中的列表值?

时间:2020-02-27 07:20:23

标签: list haskell nested

说我创建了一种新的数据类型,如下所示:

data Typex = Typex {
   level       :: Int,
   coordinate  :: (Int, Int),
   connections :: [(Int,(Int,Int),Double)]  -- edited to be a tuple
   } deriving Show

我想在使用[[TypeX]]的更高级别上修改连接。对于我的自定义类型,我是否需要嵌套循环,fmap和函子实例?或者您会提出什么建议?

2 个答案:

答案 0 :(得分:4)

您可能想要lenses

{-# LANGUAGE TemplateHaskell   #-}

import Control.Lens

data Typex = Typex
  { _level       :: Int
  , _coordinate  :: (Int, Int)
  , _connections :: [(Int,(Int,Int),Double)]
  } deriving Show
makeLenses ''Typex

main :: IO ()
main = print $ [[Typex 0 (0,0) []]
               ,[Typex 1 (1,1) [], Typex 1 (2,2) []]
               ,[]]
             & ix 1 . ix 0 . connections
                 %~ ((9,(9,9),pi):)

在此示例中,嵌套列表被索引到索引ix)到中间元素的头部,其中Typex的值集中在{{1} }字段,并在元素connections之前加上。结果:

(9,(9,9),pi)

答案 1 :(得分:2)

首先,描述您要如何修改单个连接。给它起个名字:

modConnection (i, (j, k), d) = (i + 42, (j*5, k), d)

要更新整个连接列表,请使用map

modConnections cons = map modConnection cons

要更新记录中的字段,请使用Haskell记录更新语法:

modTypeX :: TypeX -> TypeX
modTypeX tx = tx { connections = modConnections (connections tx) }

要更新这些记录的整个列表,请再次使用map

modTypeXList txs = map modTypeX txs

最后,要更新这些列表的整个列表,请再次使用map

modTypeXListList txs = map modTypeXList txs

当然,如果您不想为每个中间函数取一个名字,则不必这样做,您可以内联地做所有事情:

modTypeXListList = map . map $ \tx -> tx { connections = map modConnection (connections tx) }