说我创建了一种新的数据类型,如下所示:
data Typex = Typex {
level :: Int,
coordinate :: (Int, Int),
connections :: [(Int,(Int,Int),Double)] -- edited to be a tuple
} deriving Show
我想在使用[[TypeX]]
的更高级别上修改连接。对于我的自定义类型,我是否需要嵌套循环,fmap和函子实例?或者您会提出什么建议?
答案 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) }