gpt4 book ai didi

f# - F# 中是否有一种方法可以在不指定实例类型的情况下针对泛型类型进行类型测试?

转载 作者:行者123 更新时间:2023-12-04 17:28:19 25 4
gpt4 key购买 nike

我正在尝试对几种我关心的 SQL 生成类型进行模式匹配。理想情况下,我想这样做:

let rec getSafeValue record (prop: PropertyInfo) = 
match prop.GetValue(record, null) with
| :? string as str -> "'" + str + "'"
| :? Option<_> as opt ->
match opt with
| Some v -> getSafeValue v prop
| None -> "null"
| _ as v -> v.ToString()

问题在于,这里的类型参数为 Option<_>获取约束以匹配 record 的约束,最终只是 obj .

我知道我可以做一些基于反射的后台检查(检查它是泛型类型还是基于名称的选项类型),但如果可能的话,我宁愿避免这种情况。

最佳答案

不,没有使用 F# 的内置结构来做到这一点的好方法。但是,您可以为此类事情构建自己的可重用事件模式:

open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Quotations.Patterns

let (|UC|_|) e o =
match e with
| Lambdas(_,NewUnionCase(uc,_)) | NewUnionCase(uc,[]) ->
if (box o = null) then
// Need special case logic in case null is a valid value (e.g. Option.None)
let attrs = uc.DeclaringType.GetCustomAttributes(typeof<CompilationRepresentationAttribute>, false)
if attrs.Length = 1
&& (attrs.[0] :?> CompilationRepresentationAttribute).Flags &&& CompilationRepresentationFlags.UseNullAsTrueValue <> enum 0
&& uc.GetFields().Length = 0
then Some []
else None
else
let t = o.GetType()
if FSharpType.IsUnion t then
let uc2, fields = FSharpValue.GetUnionFields(o,t)
let getGenType (t:System.Type) = if t.IsGenericType then t.GetGenericTypeDefinition() else t
if uc2.Tag = uc.Tag && getGenType (uc2.DeclaringType) = getGenType (uc.DeclaringType) then
Some(fields |> List.ofArray)
else None
else None
| _ -> failwith "The UC pattern can only be used against simple union cases"

现在您的函数可能如下所示:
let rec getSafeValue (item:obj) = 
match item with
| :? string as str -> "'" + str + "'"
| UC <@ Some @> [v] -> getSafeValue v
| UC <@ None @> [] -> "null"
| _ as v -> v.ToString()

关于f# - F# 中是否有一种方法可以在不指定实例类型的情况下针对泛型类型进行类型测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3151099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com