F#理解歧视工会 [英] F# understanding discriminated union

查看:41
本文介绍了F#理解歧视工会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我早些时候曾问过这个问题,很抱歉再次提出类似的问题.但不幸的是,我无法真正理解如何设计一个受歧视的工会.

所以我有一堆像这样的数据结构

 

type Artist(artistId:int,name:String)=做如果名称= null,则为nullArg String.Emptynew(artistId:int)=艺术家(artistId)成员x.ArtistId = artistId成员x.Name =名称

和Genre()=让可变名称= String.Empty让可变的genreId:int = 0让可变描述= String.Empty让可变相册= List.empty成员x.说明使用get()=说明和set(value)=说明<-value
成员x.相册与get()=相册并设置(value)=相册<-值

和Album()=让可变标题= String.Empty让可变的albumId = 0让可变的genreId = 0让可变的artistId = 0让可变价格:十进制= Decimal.Zero让mutable albumArtUrl = String.Empty让可变类型= new Genre()让可变艺术家=新艺术家(artistId)成员x.Title使用get()= title和set(value)= title<-valuex.Genre成员使用get()=类型并设置(value)=类型<-value成员x.AlbumId与get()= albumId和set(value)= albumId<-value成员x.GenreId使用get()= genreId并设置(value)= genreId<-value成员x.ArtistId与get()= artistId并设置(value)= artistId<-value会员x.Price与get()=价格并设置(value)= price<-value成员x.AlbumArtUrl与get()= albumArtUrl和set(value)= albumArtUrl<-value成员x.艺术家使用get()= artist并设置(value)= artist<-value

在此处输入代码

我尝试根据F#专家的一些建议将以上内容定义为有区别的联合"

我定义如下的

类型名称=字符串输入AlbumId = int

类型Artist =|int的ArtistId|姓名艺术家

type Album =|字符串标题|小数价格|AlbumId *艺术家的相册|字符串的AlbumArtUrl

类型流派=|int的GenreId|名称类型*相册列表

在这里输入代码

但是现在我无法弄清楚我将如何像对待简单的F#类型(只是属性)那样填充受歧视的工会?

有人可以帮我解释一下吗?我一直在阅读有歧视的工会,但不会说我完全理解他们.

解决方案

区分联合用于表示具有多种不同情况的类型,这些情况大致对应于面向对象语言中的类层次结构.例如,可以这样定义基类 Shape ,其中两个继承的类分别是 Circle Rectangle :

  type Shape =|(float * float)*(float * float)的矩形//携带两个角的位置|(浮动*浮动)*浮动的圆//携带中心和直径 

您定义受歧视的工会的方式并没有真正实现您可能想要的目的.您的类型专辑艺术家流派仅代表一种具体类型.

您可以使用记录(就像带有属性的轻量级类一样)或使用区分大小写的联合带有单个大小写(对应于单个类,但语法非常轻量)来表示它们,这是主要好处.例如:

 类型名称=字符串类型价格=小数类型AlbumId = int类型ArtistId = int类型Artist = ArtistId的艺术家*名称类型专辑=专辑ID的专辑*名称*价格*艺术家 

要与一些专辑一起构建艺术家,您可以编写:

 让pinkFloyd = Artist(1,"Pink Floyd")let darkSide = Album(1,月球的黑暗面",12.0M,pinkFloyd)let finalCut = Album(2,"The Final Cut",11.0M,pinkFloyd) 

如果您随后创建一个流派,其中将包含一个专辑列表,可能还包括一个艺术家列表,因此您可以编写如下内容:

 类型类型=名称类型*艺术​​家列表*专辑列表let rock = Genre("Rock",[pinkFloyd],[darkSide; finalCut]) 

现在的问题是,您实际上如何填充这些类型.您的数据源是什么?如果要从数据库或XML文件加载数据,则可能要编写一个函数,该函数占用数据源的一部分,并返回 Artist Album ,然后在加载所有专辑和歌手之后,将它们包装在 Genre 中,并将其作为最终结果返回.

PS:回答您的问题有点困难,因为您并没有真正了解要尝试的工作.如果您可以举一个小而具体的示例(包括数据的加载及其使用),那么有人可以帮助您从更实用的角度看问题.

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 .

解决方案

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.

这篇关于F#理解歧视工会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆