本文介绍了如何将LanguagePrimitives.GenericZero / get_Zero添加到System.String?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 注:我在最后添加了很多感兴趣的评论。这些并不意味着应该使用 inline 和静态类型参数 willy nilly ,他们就在那里,这样人们就不必花很多时间去搜索与这个问题相关的许多SO问题, 我知道当需要做一个泛型函数并且需要一个零(0)值时,F#提供 GenericZero 。另外F#提供了字符串模块,但缺少GenericZero。 关于创建类型扩展参考的一个很好的教程:将函数附加到类型。 我测试过的代码: 这是一个名为 Library1 namespace Extension.Test 模块扩展= 类型System.String with 静态成员Something =a 静态成员Stati用get()=b 获得的cProp get()=c $ b $ p 这是一个名为 Workspace namespace Extension.Test module main = open扩展 [< EntryPoint>] let main argv = let stringSomething = System.String.Something printfnsomething:%sstringSomething let staticProperty = System.String.StaticProp printfnstaticProperty:%sstaticProperty let zeroProperty = System.String.Zero printfnzeroProperty:%szeroProperty let inline addTest(x: ^ a)(y:^ a):^ a = x + y let intAdd = addTest 2 LanguagePrimitives.GenericZero let floatAdd = addTest 2.0 LanguagePrimitives.GenericZero //让stringAdd = addTestaLanguagePrimitiv es.GenericZero printfnintAdd:%AintAdd printfnfloatAdd:%AfloatAdd // printfnstringAdd:%AstringAdd printf按任意键退出: System.Console.ReadKey()|>忽略 printfn 0 //返回一个整数退出码 当运行输出: something:a staticProperty:b zeroProperty:c intAdd:2 floatAdd:2.0 按任意键退出 因此,我创建并访问扩展成员,并且没有任何问题地使用GenericZero。 最后一部分是使用GenericZero作为字符串,但是取消注释行 let stringAdd = addTestaLanguagePrimitives.GenericZero 导致错误: 我没有检查 我可以添加GenericZero来输入 System.String ,我在代码中做了什么错误,或者我错过了文档中的某些东西? TL; DR 搜索时感兴趣的问题 F# - 如何扩展一个带有get_Zero的类型,这样我可以一般使用现有类型? IMO是一个误导性标题,应在阅读答案后予以更改。 F#中的get_Zero的int值是什么? 有一个来自Jack的好评: 感兴趣的F#文档 自动泛化 类型推断 类型推断的想法是,您不必指定类型的F#构造,除非编译器无法确定推导出该类型。 对于那些没有明确指定的类型,编译器根据上下文来推断类型。如果该类型不是指定的,则推断它是通用的。 泛型 静态解析类型参数 $ b 限制 内联函数 a> $ b 编辑 这是一个使用 GenericZero 对于用户定义的类型而不使用可用的扩展,并且两个变体显示 GenericZero 不适用于内部扩展和可选扩展 首先运行该程序以查看 GenericZero 然后取消注释在 Program.fs 中查看内部扩展和可选扩展名 $ b 在项目 Library1 中的 Library1.fs namespace Extension.Test module module001 = //没有扩展名 type MyType01(x:string)= member this.x = x 覆盖this.ToString()= this.x.ToString() 静态成员Something = MyType01(a) 静态成员(+)(mt1:MyType01,s:string)= MyType01(mt1:MyType01,mt2:MyType01)= MyType01(mt1.x + mt2.x) mt1.x + s)静态成员(+)(s:string,mt2:MyType01)= MyType01(s + mt2.x) 静态成员Zero with get ()= MyType01(b) //使用内部扩展类型MyType02(x:string)= member this.x = x 覆盖this.ToString()= this.x.ToString() 静态成员Something = MyType02(g)静态成员(+)(mt1:MyType02,mt2:MyType02) = MyType02(mt1.x + mt2.x)静态成员(+)(mt1:MyType02,s:string)= MyType02(mt1.x + s)静态成员(+)(s:字符串,mt2:MyType02)= MyType02(s + mt2.x) //静态成员Zero //带有get()= MyType02(h) //使用可选的扩展名 type MyType03(x:string)= member this.x = x 覆盖this.ToString()= this.x.ToString () 静态成员Something = MyType03(m)静态成员(+)(mt1:MyType03,mt2:MyType03)= MyType03(mt1.x + mt2.x) static member(+)(mt1:MyType03,s:string)= MyType03(mt1.x + s) static member(+)(s:string,mt2:MyType03)= MyType03(s + mt2 .x) //静态成员Zero // with get()= MyType03(n) module module002 = open module001 //内部扩展类型MyType02 with 静态成员Zero with get()= MyType02(h) 在 Library2.fs 项目 Library2 命名空间Extension.Test 打开module001 模块module003 = 类型MyType01与 静态成员Anything = MyType02(c) 类型MyType02与 静态成员Anything = MyType02(i ) //可选扩展名类型MyType03 with 静态成员Anything = MyType03(p) static member Zero with get()= MyType03(n) in Program.fs 项目工作区 命名空间Workspace 打开Extension.Test.module001 打开Extension.Test.module002 打开Extension.Test.module003 模块main = [ < EntryPoint>] let main argv = let staticFromBaseType = MyType01.Something printfnMyType01 staticFromBaseType:%AstaticFromBaseType let staticFromExtensionType = MyType01.Anything printfnMyType01 staticFromExtensionType:%AstaticFromExtensionType $ b $ let zeroValue = MyType01.Zero printfnMyType01 zeroValue:%AzeroValue (genericZero:MyType01)= LanguagePrimitives.GenericZero printfnMyType01 genericZero:%AgenericZero let staticFromBaseType = MyType02.Something printfnMyType02 staticFromBaseType:%AstaticFromBaseType let staticFromExtensionType = MyType02.Anything printfnMyType02 staticFromExtensionType:%Astati cFromExtensionType let zeroValue = MyType02.Zero printfnMyType02 zeroValue:%AzeroValue // let(genericZero:MyType02)= LanguagePrimitives.GenericZero // printfnMyType02 genericZero:%AgenericZero let staticFromBaseType = MyType03.Something printfnMyType03 staticFromBaseType:%AstaticFromBaseType let staticFromExtensionType = MyType03.Anything printfnMyType03 staticFromExtensionType:%AstaticFromExtensionType let zeroValue = MyType03.Zero printfnMyType03 zeroValue:%AzeroValue $ b $ // let(genericZero:MyType03)= LanguagePrimitives.GenericZero // printfnMyType03 genericZero:%AgenericZero let inline addTest(x:^ a) (y:^ a):^ a = x + y let intAdd = addTest 2 LanguagePrimitives.GenericZero let floatAdd = ad dTest 2.0 LanguagePrimitives.GenericZero let myType01Add MyType01 = addTest(MyType01(d))LanguagePrimitives.GenericZero // let(myType02Add:MyType02)= addTest(MyType02(d)) LanguagePrimitives.GenericZero // let(myType03Add:MyType03)= addTest(MyType03(o))LanguagePrimitives.GenericZero printfnintAdd:%AintAdd printfn floatAdd:%AfloatAdd printfnmyType01Add:%AmyType01Add // printfnmyType02Add:%AmyType02Add // printfnmyType03Add:%AmyType03Add printf按任意键退出: System.Console.ReadKey()|>忽略 printfn 0 //返回一个整数退出码 解决方案扩展成员不被视为成员约束解析的一部分,所以你运气不好。对于涉及多个类型的约束(例如对(+))的约束,您可以通过使用第二种类型来解决此问题,但是对于约束 GenericZero 没有好的解决方法。 Note: I added a lot of Of interest comments at the end. These are not mean to suggest that one should use inline and static type parameters willy nilly, they are there so that one does not have to spend hours searching lots of SO questions related to this question to better understand these concepts.I know that when one needs to make a function generic and needs a zero (0) value F# provides GenericZero.So this leads me to believe that to use GenericZero with a string type I only have to add a static member called Zero. Since System.String is part of the .Net framework, modifying the .Net source code is not what should be done. However F# provides Type Extensions.Also F# provides the String module, but that lacks GenericZero.For a good tutorial on creating type extensions reference: Attaching functions to types.The code I tested with:This is in a project called Library1namespace Extension.Testmodule Extensions = type System.String with static member Something = "a" static member StaticProp with get() = "b" static member Zero with get() = "c"This is in a project called Workspacenamespace Extension.Testmodule main = open Extensions [<EntryPoint>] let main argv = let stringSomething = System.String.Something printfn "something: %s" stringSomething let staticProperty = System.String.StaticProp printfn "staticProperty: %s" staticProperty let zeroProperty = System.String.Zero printfn "zeroProperty: %s" zeroProperty let inline addTest (x : ^a) (y : ^a) : ^a = x + y let intAdd = addTest 2 LanguagePrimitives.GenericZero let floatAdd = addTest 2.0 LanguagePrimitives.GenericZero// let stringAdd = addTest "a" LanguagePrimitives.GenericZero printfn "intAdd: %A" intAdd printfn "floatAdd: %A" floatAdd// printfn "stringAdd: %A" stringAdd printf "Press any key to exit: " System.Console.ReadKey() |> ignore printfn "" 0 // return an integer exit codewhen run outputs:something: astaticProperty: bzeroProperty: cintAdd: 2floatAdd: 2.0Press any key to exitSo I am creating and accessing extension members and using GenericZero without any problems.The last part is to use GenericZero for a string, however uncommenting the line let stringAdd = addTest "a" LanguagePrimitives.GenericZeroresults in the error:I did check the F# spec but found nothing of help.Can I add GenericZero to type System.String, did I do something wrong in the code, or did I miss something in the documentation?TL;DRSO questions of interest when searchingF# - How do I extend a type with get_Zero so I can use an existing type generically?which IMO is a misleading title that should be changed after reading the answers.What/where is get_Zero in F#'s int?which has a nice comment from Jack:F# documentation of interestAutomatic GeneralizationType Inference GenericsStatically Resolved Type Parameters Constraints Inline Functions EDITHere is an example that uses GenericZero for a user defined type without using an extension that works and two variations showing that GenericZero does NOT work for intrinsic extension and optional extensionRun the program first to see GenericZero work then uncomment the lines in Program.fs to see the errors for intrinsic extension and optional extension.In Library1.fs in project Library1namespace Extension.Testmodule module001 = // No extension type MyType01(x: string) = member this.x = x override this.ToString() = this.x.ToString() static member Something = MyType01("a") static member (+) (mt1 : MyType01, mt2 : MyType01) = MyType01(mt1.x + mt2.x) static member (+) (mt1 : MyType01, s : string) = MyType01(mt1.x + s) static member (+) (s : string, mt2 : MyType01) = MyType01(s + mt2.x) static member Zero with get() = MyType01("b") // uses intrinsic extension type MyType02(x: string) = member this.x = x override this.ToString() = this.x.ToString() static member Something = MyType02("g") static member (+) (mt1 : MyType02, mt2 : MyType02) = MyType02(mt1.x + mt2.x) static member (+) (mt1 : MyType02, s : string) = MyType02(mt1.x + s) static member (+) (s : string, mt2 : MyType02) = MyType02(s + mt2.x)// static member Zero// with get() = MyType02("h") // uses optional extension type MyType03(x: string) = member this.x = x override this.ToString() = this.x.ToString() static member Something = MyType03("m") static member (+) (mt1 : MyType03, mt2 : MyType03) = MyType03(mt1.x + mt2.x) static member (+) (mt1 : MyType03, s : string) = MyType03(mt1.x + s) static member (+) (s : string, mt2 : MyType03) = MyType03(s + mt2.x)// static member Zero// with get() = MyType03("n")module module002 = open module001 // intrinsic extension type MyType02 with static member Zero with get() = MyType02("h")in Library2.fs in project Library2namespace Extension.Testopen module001module module003 = type MyType01 with static member Anything = MyType02("c") type MyType02 with static member Anything = MyType02("i") // optional extension type MyType03 with static member Anything = MyType03("p") static member Zero with get() = MyType03("n")in Program.fs in project Workspacenamespace Workspaceopen Extension.Test.module001open Extension.Test.module002open Extension.Test.module003module main = [<EntryPoint>] let main argv = let staticFromBaseType = MyType01.Something printfn "MyType01 staticFromBaseType: %A" staticFromBaseType let staticFromExtensionType = MyType01.Anything printfn "MyType01 staticFromExtensionType: %A" staticFromExtensionType let zeroValue = MyType01.Zero printfn "MyType01 zeroValue: %A" zeroValue let (genericZero: MyType01) = LanguagePrimitives.GenericZero printfn "MyType01 genericZero: %A" genericZero let staticFromBaseType = MyType02.Something printfn "MyType02 staticFromBaseType: %A" staticFromBaseType let staticFromExtensionType = MyType02.Anything printfn "MyType02 staticFromExtensionType: %A" staticFromExtensionType let zeroValue = MyType02.Zero printfn "MyType02 zeroValue: %A" zeroValue// let (genericZero: MyType02) = LanguagePrimitives.GenericZero// printfn "MyType02 genericZero: %A" genericZero let staticFromBaseType = MyType03.Something printfn "MyType03 staticFromBaseType: %A" staticFromBaseType let staticFromExtensionType = MyType03.Anything printfn "MyType03 staticFromExtensionType: %A" staticFromExtensionType let zeroValue = MyType03.Zero printfn "MyType03 zeroValue: %A" zeroValue// let (genericZero: MyType03) = LanguagePrimitives.GenericZero// printfn "MyType03 genericZero: %A" genericZero let inline addTest (x : ^a) (y : ^a) : ^a = x + y let intAdd = addTest 2 LanguagePrimitives.GenericZero let floatAdd = addTest 2.0 LanguagePrimitives.GenericZero let (myType01Add : MyType01) = addTest (MyType01("d")) LanguagePrimitives.GenericZero// let (myType02Add : MyType02) = addTest (MyType02("d")) LanguagePrimitives.GenericZero// let (myType03Add : MyType03) = addTest (MyType03("o")) LanguagePrimitives.GenericZero printfn "intAdd: %A" intAdd printfn "floatAdd: %A" floatAdd printfn "myType01Add: %A" myType01Add// printfn "myType02Add: %A" myType02Add// printfn "myType03Add: %A" myType03Add printf "Press any key to exit: " System.Console.ReadKey() |> ignore printfn "" 0 // return an integer exit code 解决方案 Extension members aren't considered as part of member constraint resolution, so you're out of luck. With constraints that involve more than one type (such as the constraint on (+)), you can work around this via the use of a second type, but for the constraint on GenericZero there's no good workaround. 这篇关于如何将LanguagePrimitives.GenericZero / get_Zero添加到System.String?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-22 23:09