2012-02-08 43 views
2

我有點問過這個問題,所以很抱歉再次提出類似的問題。但不幸的是我不能真正理解如何設計一個歧視的工會。F#瞭解歧視工會

,所以我有一堆看起來像

 

type Artist(artistId : int, name : String) = do if name = null then nullArg String.Empty new(artistId: int) = Artist(artistId) member x.ArtistId = artistId member x.Name = name

and Genre() = let mutable name = String.Empty let mutable genreId : int = 0 let mutable description = String.Empty let mutable albums = List.empty member x.Description with get() = description and set(value) = description <- value
member x.Albums with get() = albums and set (value) = albums <- value

and Album() = let mutable title = String.Empty let mutable albumId = 0 let mutable genreId = 0 let mutable artistId = 0 let mutable price : decimal = Decimal.Zero let mutable albumArtUrl = String.Empty let mutable genre = new Genre() let mutable artist = new Artist(artistId) member x.Title with get() = title and set (value) = title <- value member x.Genre with get() = genre and set (value) = genre <- value member x.AlbumId with get() = albumId and set (value) = albumId <- value member x.GenreId with get() = genreId and set (value) = genreId <- value member x.ArtistId with get() = artistId and set (value) = artistId <- value member x.Price with get() = price and set (value) = price <- value member x.AlbumArtUrl with get() = albumArtUrl and set (value) = albumArtUrl <- value member x.Artist with get() = artist and set (value) = artist <- value

enter code here

I tried defining the above as a Discriminated union based on suggestions by some of F# guru's

which i defined like below

type Name = string type AlbumId = int

type Artist = | ArtistId of int | Artist of Name

type Album = | Title of string | Price of decimal | Album of AlbumId * Artist | AlbumArtUrl of string

type Genre = | GenreId of int | Genre of Name * Album list

enter code here

數據結構,但現在我無法弄清楚如何將我填充我識別聯合同樣地,我與這只是性質我簡單的F#類型做什麼? 。

有人可以幫我解釋一下嗎?我一直在閱讀歧視工會,但不會說我完全理解他們。

+1

考慮到您最近一直在問的所有F#問題,在這一點上,真的值得您花時間閱讀F#上的Wikibook (由可敬的@Juliet撰寫)或投資於F#的書籍。朱麗葉的Wikibook非常好,所以你可能想從那裏開始。但是沒有任何意思 - 你需要花點時間明智地去嘗試一些基本原理。我認爲如果你這樣做,你會更好地掌握F#。 – 2012-02-08 20:29:09

回答

6

判別聯合用於表示具有多種不同情況的類型,它們大致對應於面嚮對象語言中的類層次結構。例如,一個基類Shape有兩個繼承類CircleRectangle可能是這樣定義的:你定義了識別聯合

type Shape = 
    | Rectangle of (float * float) * (float * float) // Carries locations of two corners 
    | Circle of (float * float) * float    // Carries center and diameter 

的方式並沒有真正做什麼你可能打算。您的類型AlbumArtistGenre僅代表一種具體類型。

可以代表這些與任何記錄(這就像輕量級的班,只是性質),或者使用可識別聯合有一個案例,這相當於一個類,但有一個非常輕量級語法,這是主要好處。例如:

type Name = string 
type Price = decimal 
type AlbumId = int 
type ArtistId = int 

type Artist = Artist of ArtistId * Name 
type Album = Album of AlbumId * Name * Price * Artist 

要帶幾張專輯一起構建一個藝術家,你可以這樣寫:

let pinkFloyd = Artist(1, "Pink Floyd") 

let darkSide = Album(1, "The Dark Side of the Moon", 12.0M, pinkFloyd) 
let finalCut = Album(2, "The Final Cut", 11.0M, pinkFloyd) 

如果然後創建一個流派,將包含專輯列表和可能列表藝術家,所以你可以寫這樣的事情:

type Genre = Genre of Name * Artist list * Album list 

let rock = Genre("Rock", [pinkFloyd], [darkSide; finalCut]) 

現在的問題是,你怎麼竟要填充的類型。你的數據源是什麼?如果您要從數據庫或XML文件加載數據,則可能需要編寫一個函數,該函數需要部分數據源並返回ArtistAlbum,並且在加載所有專輯和藝術家後,將它們包裹在Genre並將其作爲最終結果返回。

PS:回答你的問題有點困難,因爲你並沒有真正給出你想要做什麼的更大圖景。如果你可以給出一個小的,但具體的例子(包括數據加載和使用),那麼有人可以幫助你從更實用的角度來看問題。

+0

真的很抱歉@托馬斯,我沒有打算讓我的問題難以理解。即時通訊的嘗試是遵循本教程http://mvcmusicstore.codeplex。com,你可以下載pdf,如果你喜歡,這是在C#中,並將應用程序轉換爲F#。完全相同的應用程序只是想在此過程中學習函數式編程/ F#。 – netmatrix01 2012-02-08 14:33:39

+0

你的回答在幫助我理解歧視工會和我們能夠實現的目標方面有相當大的幫助。但是當我的類型是相互遞歸時,我將如何解決這個問題。由於流派類型也包含專輯作爲屬性。通過使用歧視聯盟來定義域時,這可能嗎? – netmatrix01 2012-02-08 14:57:29

+3

@ netmatrix01如果你想使用相互遞歸的類型,那麼你通常需要變體和類。但是,如果您的「專輯」存儲在「流派」中,您是否真的需要將「專輯」的引用存儲到「流派」?當你列出例如在指定類型的專輯中,您始終會知道流派名稱。同樣,當你顯示一個特定的專輯時,如果你走過對象結構,你總是會知道這個流派。所以,我想我可能會嘗試避免這種應用程序中的遞歸結構。 – 2012-02-08 15:15:19