Я пытаюсь переучивать системный анализ. У меня много объектно-ориентированного мышления, для которого я пока не могу найти эквиваленты в Haskell.
Вымышленная система состоит из станций скорой помощи, скорой помощи и экипажа. (Он уже получает объект-y.) Все это состояние можно обернуть в большой тип SystemState. SystemState [Станции] [Машины скорой помощи] [Экипаж]. Затем я могу создавать функции, которые принимают SystemState, и возвращать новый SystemState.
module AmbSys
( version
, SystemState
, Station
, Ambulance
, Crew
) where
version = "0.0.1"
data SystemState = SystemState [Station] [Ambulance] [Crew] deriving (Show)
data Station = Station { stName :: String
, stAmbulances :: [Ambulance]
} deriving (Show)
data Ambulance = Ambulance { amCallSign :: String
, amStation :: Station
, amCrew :: [Crew]
} deriving (Show)
data Crew = Crew { crName :: String
, crAmbulance :: Ambulance
, crOnDuty :: Bool
} deriving (Show)
Здесь сеанс ghci, где я создаю некоторые данные.
*AmbSys> :load AmbSys
[1 of 1] Compiling AmbSys ( AmbSys.hs, interpreted )
Ok, modules loaded: AmbSys.
*AmbSys> let s = Station "London" []
*AmbSys> let a = Ambulance "ABC" s []
*AmbSys> let s' = Station "London" [a]
*AmbSys> let c = Crew "John Smith" a False
*AmbSys> let a' = Ambulance "ABC" s [c]
*AmbSys> let s'' = Station "London" [a']
*AmbSys> let system_state = SystemState [s''] [a'] [c]
*AmbSys> system_state
SystemState [Station {stName = "London", stAmbulances = [Ambulance {amCallSign = "ABC",
amStation = Station {stName = "London", stAmbulances = []}, amCrew = [Crew
{crName = "John Smith", crAmbulance = Ambulance {amCallSign = "ABC",
amStation = Station {stName = "London", stAmbulances = []}, amCrew = []},
crOnDuty = False}]}]}] [Ambulance {amCallSign = "ABC", amStation = Station {
stName = "London", stAmbulances = []}, amCrew = [Crew {crName = "John Smith",
crAmbulance = Ambulance {amCallSign = "ABC", amStation = Station {stName = "London",
stAmbulances = []}, amCrew = []}, crOnDuty = False}]}] [Crew {crName = "John Smith",
crAmbulance = Ambulance {amCallSign = "ABC", amStation = Station {stName = "London",
stAmbulances = []}, amCrew = []}, crOnDuty = False}]
Здесь вы можете увидеть несколько проблем:
- Я не смог создать согласованный SystemState - некоторые из значений являются "старыми" значениями, такими как s или s ', а не s' '.
- много ссылок на "те же" данные имеют отдельные копии.
Теперь я мог бы создать функцию, которая берет имя члена SystemState и члена команды, которое возвращает новый SystemState, где член этого экипажа "отключен".
Моя проблема в том, что я должен найти и изменить члена экипажа в скорой помощи и (идентичной копии) члена экипажа в SystemState.
Это возможно для небольших систем, но реальные системы имеют гораздо больше связей. Это похоже на проблему n-квадрата.
Я прекрасно понимаю, что я думаю о системе объектно-ориентированным образом.
Как бы такая система была правильно создана в Haskell?
Редактировать: Спасибо всем за ваши ответы, а также тем, кто на reddit тоже http://www.reddit.com/r/haskell/comments/b87sc/how_do_you_manage_an_object_graph_in_haskell/
Теперь я понимаю, что могу делать то, что хочу в Haskell. С другой стороны, похоже, что диаграммы объектов/записей/структур не являются объектами "первого класса" в Haskell (как и в C/Java/и т.д.) Из-за необходимого отсутствия ссылок. Там просто компромисс - некоторые задачи синтаксически проще в Haskell, некоторые из них более простые (и более небезопасные) в C.