F # понимание дискриминационного союза - PullRequest
2 голосов
/ 08 февраля 2012

Я как бы задавал этот вопрос ранее, так что извините за повторный вопрос.Но, к сожалению, я не в состоянии по-настоящему понять, как создавать дискриминационные союзы.

, поэтому у меня есть куча структур данных, которые выглядят как

</p>

<p>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</p>

<p>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<br>
        member x.Albums
            with get() = albums and set ( value ) = albums <- value</p>

<p>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</p>

<p>enter code here</p>

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

<p>which i defined like below</p>

<p>
</p>

<p>type Name = string
type AlbumId = int</p>

<p>type Artist = 
    | ArtistId of int
    | Artist of Name </p>

<p>type Album = 
    | Title of string
    | Price of decimal
    | Album of AlbumId * Artist
    | AlbumArtUrl of string</p>

<p>type Genre = 
    | GenreId of int
    | Genre of Name * Album list     </p>

enter code here

Но теперь я не могу понять, как бы я заполнил свой различимый союз аналогично тому, как я делал с моим простым F #типы, которые являются просто свойствами?

Может кто-нибудь помочь мне объяснить это?Я читал о дискриминационных союзах, но не скажу, что полностью их понимаю.

1 Ответ

7 голосов
/ 08 февраля 2012

Дискриминационные объединения используются для представления типов в нескольких различных случаях, что примерно соответствует иерархии классов в объектно-ориентированных языках. Например, базовый класс 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: Сложно ответить на ваши вопросы, потому что вы на самом деле не представляете более полную картину того, что вы пытаетесь сделать. Если вы можете привести небольшой, но конкретный пример (включая загрузку данных и их использование), то кто-то может помочь вам взглянуть на проблему с более функциональной точки зрения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...