Generics 如何将F#联合类型的使用限制为特定选项
我在自学F#——为了乐趣和利益--虽然我取得了一些进展,但在使用代数类型时遇到了一个绊脚石。下面是一个JSON类型,我将其编码为将任意JSON结构序列化为字符串。当然,我对其设计和效率的主观评价持开放态度,但我主要关注第7行:Generics 如何将F#联合类型的使用限制为特定选项,generics,f#,algebraic-data-types,discriminated-union,Generics,F#,Algebraic Data Types,Discriminated Union,我在自学F#——为了乐趣和利益--虽然我取得了一些进展,但在使用代数类型时遇到了一个绊脚石。下面是一个JSON类型,我将其编码为将任意JSON结构序列化为字符串。当然,我对其设计和效率的主观评价持开放态度,但我主要关注第7行: type JSON = | JString of string | JNumber of decimal | JBool of bool | JNull | JArray of JSON list | JObject
type JSON =
| JString of string
| JNumber of decimal
| JBool of bool
| JNull
| JArray of JSON list
| JObject of Map< JSON, JSON >
with
member this.Serialize =
let rec serialize ( element : JSON ) =
match element with
| JString str ->
"\"" + str + "\""
| JNumber num ->
num.ToString()
| JBool bln ->
bln.ToString().ToLower()
| JNull ->
"null"
| JArray ary ->
"[" + String.concat "," ( List.map serialize ary ) + "]"
| JObject obj ->
"{" + (
Map.fold (
fun state key value ->
state + ( match state with "" -> "" | _ -> "," )
+ ( serialize key )
+ ":"
+ ( serialize value ) ) "" obj ) + "}"
serialize( this )
typejson=
|字符串的JString
|十进制数
|布尔的JBool
|JNull
|JSON列表的JArray
|Map的JObject
具有
此成员。序列化=
让rec序列化(元素:JSON)=
匹配元素
|JString str->
“\”“+str+”\“”
|JNumber num->
num.ToString()
|JBool bln->
bln.ToString().ToLower()文件
|JNull->
“空”
|JArray ary->
[“+String.concat”,“(List.map序列化变量)+“]
|JObject对象->
"{" + (
地图折叠(
趣味状态键值->
状态+(将状态与“->”匹配
+(序列化密钥)
+ ":"
+(序列化值))“obj)+“}”
序列化(此)
熟悉JSON的人都知道,JSON对象的键/值对应该被设置在字符串上,而不仅仅是任何JSON元素/值。有没有办法进一步限制映射的第一个类型参数?当然,这些都不起作用:
type JSON =
... elided ...
| JObject of Map< JSON.JString, JSON >
typejson=
... 省略。。。
|Map的JObject
typejson=
... 省略。。。
|Map的JObject
typejson=
... 省略。。。
|Map的JObject
谢谢。从受歧视的联合中引用另一个案例标识符是不可能的。从 语法 [属性] 类型[accessibility modifier]类型名称= |案例标识符1[属于[fieldname1:]类型1[*[fieldname2:]类型2…] |案例标识符2[属于[fieldname3:]类型3[*[fieldname4:]类型4…] [委员名单] 这意味着每个案例标识符必须是某种类型的
。案例标识符本身是而不是类型
实现相同功能的一种方法是将受歧视的联合分解为多个受歧视的联合:
type JSONKey =
| JString of string
type JSONValue =
| JString of string
| JNumber of decimal
| JBool of bool
| JNull
| JArray of JSONValue list
| JObject of Map<JSONKey, JSONValue>
然后,serialize
需要更改为let rec serialize(元素:JSONValue)
和
serialize(this)
需要更改为serialize(JObject this)
正如@Ringil提到的,Map
将在这种情况下工作,但这不是太好的扩展性/限制性。JObject of Map
在我的计算机上工作……我将再次研究使用string作为键。我在JObject的序列化过程中遇到了问题。谢谢。案例标识符不正确a型是我在这一点上失去的一种区别。我或多或少地把它们看作是亚型。我很感谢您的澄清和建议的解决方案。
type JSON =
... elided ...
| JObject of Map< string, JSON >
type JSONKey =
| JString of string
type JSONValue =
| JString of string
| JNumber of decimal
| JBool of bool
| JNull
| JArray of JSONValue list
| JObject of Map<JSONKey, JSONValue>
type JSON = Map<JSONKey, JSONValue>