我正試圖重新學習系統分析。我有很多面向對象的思想,但我無法在Haskell中找到等價物。一個虛構的系統由救護車站,救護車和乘員組組成。 (它已經獲得了object-y。)所有這個狀態都可以包含在一個大的SystemState類型中。 SystemState [車站] [救護車] [乘員組]。然後我可以創建帶有SystemState的函數,並返回一個新的SystemState。如何管理Haskell中的對象圖?
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.
謝謝,這非常好地解決了偶然的問題之一。 – fadedbee 2010-03-02 13:55:10
我將「Key」定義爲「newtype Key a = Key String derived(Eq,Ord,Show)」。它只是在三種不同的密鑰類型之間節省了少量的重複。 – 2010-03-02 22:14:58