传递"generic" JsonProvider 以在 F# 中运行



我有两个JSONPROVIDER类型:

type Provider1 = JsonProvider<"""{structure}""">
type Provider2 = JsonProvider<"""{}structure2""">

我想拥有一个函数,可以接受这些功能,并使用提供的JSONPROVIDER来解析JSON,类似的内容:(伪代码,而不是编译)

let parseUsingSpecificProvider json (provider : JsonProvider<GENERIC>) =
    provider.Parse json

您可以使用静态分辨类型参数(SRTPS)定义内联函数:

let inline parseUsingSpecificProvider json (provider:^T) =
    (^T : (static member Parse : string -> _) json) 
// tests
#r @"packagesFSharp.Datalibnet40FSharp.Data.dll"
open FSharp.Data
type Provider1 = JsonProvider<""" { "name":"John"           } """>
type Provider2 = JsonProvider<""" { "name":"John", "age":94 } """>
let x = parseUsingSpecificProvider  (""" { "name":"Tomas", "age":4 } """) Unchecked.defaultof<Provider1>
let y = parseUsingSpecificProvider  (""" { "name":"Tomas", "age":4 } """) Unchecked.defaultof<Provider2>

因此,它将与具有静态方法Parse接受字符串作为输入的任何类型一起使用。

在功能编程中,通常将'单函数接口'替换为函数本身。IE。只需将Parse函数用作第一类值:

,而不是传递具有Parse方法的解析器。
#r @"packagesFSharp.Datalibnet40FSharp.Data.dll"
open FSharp.Data
type Provider1 = JsonProvider<""" { "name":"John"           } """>
type Provider2 = JsonProvider<""" { "name":"John", "age":94 } """>
let parse parseFn json =
    parseFn json
let p1 = parse Provider1.Parse """{ "name": "Not John" }"""
let p2 = parse Provider2.Parse """{ "name": "Not John either", "age": 12 }"""

如果您需要几种提供类型的方法,则可以使用例如包含所有必要数据的记录:

type Parser<'b> = {
    Parse : string -> 'b
    GetSample : unit -> 'b
}
let parseUsing parser text =
    printfn "Parsing things like %A" <| parser.GetSample()
    parser.Parse text
let parser1 = { Parse = Provider1.Parse; GetSample = Provider1.GetSample }
let parser2 = { Parse = Provider2.Parse; GetSample = Provider2.GetSample }
let p1' = parseUsing parser1 """{ "name": "Not John" }"""
let p2' = parseUsing parser2 """{ "name": "Not John either", "age": 12 }"""

虽然SRTP强大(和酷),但它们的用法应受到限制。过度使用会减慢编译器并使代码更难理解。

最新更新