我之前有点问过这个问题,很遗憾再次提出类似的问题。但不幸的是,我无法真正理解如何设计一个受歧视的工会。
所以我有一堆看起来像
的数据结构
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#类型?
有人可以帮我解释一下吗?我一直在阅读有歧视的工会,但不会说我完全理解它们。
答案 0 :(得分:6)
被区分的联合用于表示具有多种不同情况的类型,这大致对应于面向对象语言中的类层次结构。例如,具有两个Shape
和Circle
的继承类的基类Rectangle
可能会像这样定义:
type Shape =
| Rectangle of (float * float) * (float * float) // Carries locations of two corners
| Circle of (float * float) * float // Carries center and diameter
您定义受歧视的工会的方式实际上并不符合您的意图。您的类型Album
,Artist
和Genre
仅代表一种具体类型。
你可以用任何一个记录来表示这些记录(就像只有属性的轻量级类)或者使用带有单个案例的的歧视联合,它对应于单个类,但是具有非常轻量级的语法,这是主要的好处。例如:
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文件加载数据,那么您可能希望编写一个函数来获取数据源的某些部分并返回Artist
或Album
并在您加载所有数据之后专辑和艺术家,将它们包装在Genre
内并作为最终结果返回。
PS:回答你的问题有点困难,因为你并没有真正全面了解你的目标。如果你能给出一个小的但具体的例子(包括加载数据及其使用),那么有人可以帮助你从更具功能性的角度来看问题。