Как изменить значение списка во вложенном пользовательском типе данных? - PullRequest
3 голосов
/ 27 февраля 2020

Скажем, я создал новый тип данных следующим образом:

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

Я хочу изменить соединения с верхнего уровня, где я использую [[TypeX]]. Нужны ли мне вложенные циклы, fmap и экземпляр функтора для моего пользовательского типа или что бы вы предложили?

Ответы [ 2 ]

4 голосов
/ 27 февраля 2020

Вы, вероятно, хотите линзы .

{-# 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 значении, сфокусированном на поле connections, и там элемент (9,(9,9),pi) добавлен. Результат:

[[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 = []}],[]]
2 голосов
/ 27 февраля 2020

Сначала опишите, как вы хотите изменить одно соединение. Дайте ему имя:

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) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...