LHurttila
LHurttila

Reputation: 37

How to modify a list value in a nested custom datatype?

Say I've made a new data type as follows:

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

I want to modify the connections from an upper level where I use [[TypeX]]. Do I need nested loops, fmap and a functor instance for my custom type or what would you suggest?

Upvotes: 3

Views: 174

Answers (2)

Fyodor Soikin
Fyodor Soikin

Reputation: 80714

First, describe how you want to modify a single connection. Give it a name:

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

To update a whole list of connections, use map:

modConnections cons = map modConnection cons

To update a field in the record, use the Haskell record update syntax:

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

To update a whole list of these records, use map again:

modTypeXList txs = map modTypeX txs

And finally, to update a whole list of these lists, use map once again:

modTypeXListList txs = map modTypeXList txs

Of course, if you don't want to give a name to every intermediate function, you don't have to, you can do everything inline:

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

Upvotes: 2

leftaroundabout
leftaroundabout

Reputation: 120711

You probably want 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):)

In this example, the the nested list is indexed (ix) into the head of the middle element, in that Typex value focused on the connections field, and there the element (9,(9,9),pi) prepended. Result:

[[Typex {_level = 0, _coordinate = (0,0), _connections = []}],[Typex {_level = 1, _coordinate = (1,1), _connections = [(9,(9,9),3.141592653589793)]},Typex {_level = 1, _coordinate = (2,2), _connections = []}],[]]

Upvotes: 4

Related Questions