注意:我在末尾添加了许多Of interest
注释。这些并不是要建议一个人使用inline
和static type parameters
willy nilly,所以他们不必花大量时间搜索与该问题相关的大量SO问题就可以更好地理解这些概念。
我知道,当需要使函数通用并且需要零(0)值时,F#提供GenericZero。
因此,这使我相信使用字符串类型的GenericZero
只需添加一个名为Zero的静态成员。
由于System.String是.Net框架的一部分,因此不应修改.Net源代码。但是F#提供了Type Extensions。
F#还提供了String module,但是缺少GenericZero。
有关创建类型扩展的良好教程,请引用:Attaching functions to types。
我测试过的代码:
这在一个名为Library1
的项目中
namespace Extension.Test
module Extensions =
type System.String with
static member Something = "a"
static member StaticProp
with get() = "b"
static member Zero
with get() = "c"
这在一个名为
Workspace
的项目中namespace Extension.Test
module 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 code
运行时输出:
something: a
staticProperty: b
zeroProperty: c
intAdd: 2
floatAdd: 2.0
Press any key to exit
因此,我正在创建和访问扩展成员,并使用GenericZero没有任何问题。
最后一部分是对字符串使用GenericZero,但是取消注释行
let stringAdd = addTest "a" LanguagePrimitives.GenericZero
导致错误:
我确实检查了F# spec,但没有发现任何帮助。
我可以将GenericZero添加为
System.String
类型吗,我在代码中做错了什么吗?还是我错过了文档中的某些内容?TL; DR
这样搜索时感兴趣的问题
F# - How do I extend a type with get_Zero so I can use an existing type generically?
该IMO是一个误导性标题,应在阅读答案后进行更改。
What/where is get_Zero in F#'s int?
jack 有一个很好的评论:
感兴趣的F#文档
Automatic Generalization
Type Inference
Generics
Statically Resolved Type Parameters
Constraints
Inline Functions
编辑
这是一个示例,它使用
GenericZero
作为用户定义的类型,而不使用有效的扩展名,并且两个变体表明GenericZero
对intrinsic extension
和optional extension
不起作用首先运行程序以查看
GenericZero
的工作原理,然后取消注释Program.fs
中的行以查看intrinsic extension
和optional extension
的错误。在项目
Library1.fs
中的Library1
中namespace Extension.Test
module 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")
在项目
Library2.fs
中的Library2
中namespace Extension.Test
open module001
module 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")
在项目
Program.fs
中的Workspace
中namespace Workspace
open Extension.Test.module001
open Extension.Test.module002
open Extension.Test.module003
module 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
最佳答案
扩展成员不被视为成员约束解决方案的一部分,因此您很不走运。对于涉及多个类型的约束(例如(+)
的约束),您可以通过使用第二种类型来解决,但是对于GenericZero
的约束,没有很好的解决方法。
关于generics - 如何将LanguagePrimitives.GenericZero/get_Zero添加到System.String?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37117089/