问题
I've kind of asked this question earlier so sorry for asking a bit similar question again. But unfortunately im not able to really understand how to design a discriminated unions.
so i have bunch of data structures which look like
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
But now i unable to figure out how would i populate my discriminated union similarly i was doing with my simple F# types which are just properties ?.
Can someone help me to explain this ?. I have been reading on discriminated unions but wont say i fully understand them .
回答1:
Discriminated unions are used to represent types with multiple different cases, which roughly corresponds to class hierarchies in object oriented langauges. For example, a base class Shape
with two inherited classes for Circle
and Rectangle
might be defined like this:
type Shape =
| Rectangle of (float * float) * (float * float) // Carries locations of two corners
| Circle of (float * float) * float // Carries center and diameter
The way you defined your discriminated unions does not really do what you probably intended. Your types Album
, Artist
and Genre
represent just a single concrete type.
You can represent these with either records (which are just like lightweight classes with just properties) or using discriminated unions with a single case, which corresponds to a single class, but has a pretty lightweight syntax, which is the main benefit. For example:
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
To construct an artist together with a few albums, you can write:
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)
If you then create a genre, that will contain a list of albums and possibly a list of artists, so you could write something like this:
type Genre = Genre of Name * Artist list * Album list
let rock = Genre("Rock", [pinkFloyd], [darkSide; finalCut])
The question now is, how do you actually want to populate the types. What is your data-source? If you're loading data from a database or from a XML file, you're probably want to write a function that takes some part of the data source and returns Artist
or Album
and after you load all albums and artists, wrap them inside a Genre
and return that as a final result.
PS: It is a bit difficult to answer your questions, because you're not really giving a bigger picture of what you're trying to do. If you can give a small, but concrete example (including the loading of data and their use), then someone can help you to look at the problem from a more functional perspective.
来源:https://stackoverflow.com/questions/9194692/f-understanding-discriminated-union