Types 是";隐式重载“;可能的

Types 是";隐式重载“;可能的,types,f#,arguments,overloading,implicit,Types,F#,Arguments,Overloading,Implicit,我有下面的例子: type Stream (capacity) = let data = Array.zeroCreate capacity member private s.position = ref 0 static member private encoder = new Text.UTF8Encoding() static member private write (x, o, a : byte[]) = for i = 0 to 3 do a.[o +

我有下面的例子:

type Stream (capacity) =
    let data = Array.zeroCreate capacity
    member private s.position = ref 0
    static member private encoder = new Text.UTF8Encoding()
    static member private write (x, o, a : byte[]) = for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256)
    static member private write (x, o, a : byte[]) = for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s)
    static member private write (x : string, o : int, a : byte[]) = Stream.encoder.GetBytes(x, 0, x.Length, a, o)
    static member format (x : int, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
    static member format (x : int16, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
    static member format (x : string, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
类型流(容量)=
让data=Array.zero创建容量
成员私人s.position=参考0
静态成员私有编码器=新文本。UTF8Encoding()
静态成员私有写入(x,o,a:byte[])=对于i=0到3执行a.[o+i]>>24-i*8)%256)
静态成员私有写入(x,o,a:byte[])=对于i=0到1执行a.[o+i]>>24-i*8)%256s)
静态成员私有写入(x:string,o:int,a:byte[])=Stream.encoder.GetBytes(x,0,x.Length,a,o)
静态成员格式(x:int,s)=让a=Array.creates0uy在Stream.write(x,0,a);A.
静态成员格式(x:int16,s)=让a=Array.create在Stream.write(x,0,a)中创建s0uy;A.
静态成员格式(x:string,s)=让a=Array.creates0uy在Stream.write(x,0,a);A.
首先,很抱歉代码非常混乱,我只是F#的初学者。正如您可能看到的那样,三个
格式
重载只因其参数类型不同而不同,而它们的主体是相同的(尽管调用
写入
的不同重载)。是否有可能将格式函数减少到一个,可能是内联的


如果我完全没有抓住要点,我很抱歉,但是我找不到关于这件事的更多信息。

我认为你写这篇文章的方式可能是最好的选择

如果不想装箱,那么肯定需要重载的
write
函数,因为序列化需要针对不同的类型以不同的方式实现。在这种情况下,使用
inline
成员也不起作用,因为
inline
函数只能在它获得的某个值上要求特定的实例或静态方法,而不能要求特定的重载

避免某些重复的合理解决方案是只定义一个重载函数(即
write
),然后在其他函数需要时将其作为参数显式传递给其他函数。你可以这样写:

type Stream (capacity) = 
    let data = Array.zeroCreate capacity 
    member private s.position = ref 0 
    static member private encoder = new Text.UTF8Encoding() 
    static member Write (x, o, a : byte[]) = 
        for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256) 
    static member Write (x, o, a : byte[]) = 
        for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s) 
    static member Write (x : string, o : int, a : byte[]) = 
        Stream.encoder.GetBytes(x, 0, x.Length, a, o) |> ignore
    // Format takes a writer function 'f' as the first argument
    static member Format (x, s) f = let a = Array.create s 0uy in f(x, 0, a); a 

// When you call 'Format' with 'Stream.Write' as an argument, 
// the compiler chooses the right overload for you
Stream.Format (1s, 100) Stream.Write 
Stream.Format ("foo", 100) Stream.Write 

。。。但这是一个更复杂的解决方案,在调用
格式时还需要编写一些额外的代码,因此我不会真正使用这种方法(但知道它的存在可能会很有用)。

我认为您编写它的方式可能是最好的选择

如果不想装箱,那么肯定需要重载的
write
函数,因为序列化需要针对不同的类型以不同的方式实现。在这种情况下,使用
inline
成员也不起作用,因为
inline
函数只能在它获得的某个值上要求特定的实例或静态方法,而不能要求特定的重载

避免某些重复的合理解决方案是只定义一个重载函数(即
write
),然后在其他函数需要时将其作为参数显式传递给其他函数。你可以这样写:

type Stream (capacity) = 
    let data = Array.zeroCreate capacity 
    member private s.position = ref 0 
    static member private encoder = new Text.UTF8Encoding() 
    static member Write (x, o, a : byte[]) = 
        for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256) 
    static member Write (x, o, a : byte[]) = 
        for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s) 
    static member Write (x : string, o : int, a : byte[]) = 
        Stream.encoder.GetBytes(x, 0, x.Length, a, o) |> ignore
    // Format takes a writer function 'f' as the first argument
    static member Format (x, s) f = let a = Array.create s 0uy in f(x, 0, a); a 

// When you call 'Format' with 'Stream.Write' as an argument, 
// the compiler chooses the right overload for you
Stream.Format (1s, 100) Stream.Write 
Stream.Format ("foo", 100) Stream.Write 

。。。但这是一个更为复杂的解决方案,在调用
format
时还需要编写一些额外的代码,因此我不会真正使用这种方法(但知道它的存在可能会有用)。

重构
format
函数是显而易见的;您可以创建通用格式函数并传递不同的
流。将
函数作为参数写入。首先,将泛型函数置于类的任何成员之前:

    static let formatGeneric writeFunc x s =
           let a = Array.create s 0uy         
           writeFunc(x, 0, a)         
           a
并使用它来实例化不同的格式函数:

    static member format (x, s) = 
           formatGeneric (fun (x: int, i, a) -> Stream.write(x, i, a)) x s
    static member format (x, s) = 
           formatGeneric (fun (x: int16, i, a) -> Stream.write(x, i, a)) x s
    static member format (x, s) = 
           formatGeneric (fun (x: string, i, a) -> Stream.write(x, i, a)) x s

请注意,
Stream.write
是以完整形式编写的,并且对
x
类型进行了注释,以选择合适的重载。

重构
格式
函数是显而易见的;您可以创建通用格式函数并传递不同的
流。将
函数作为参数写入。首先,将泛型函数置于类的任何成员之前:

    static let formatGeneric writeFunc x s =
           let a = Array.create s 0uy         
           writeFunc(x, 0, a)         
           a
并使用它来实例化不同的格式函数:

    static member format (x, s) = 
           formatGeneric (fun (x: int, i, a) -> Stream.write(x, i, a)) x s
    static member format (x, s) = 
           formatGeneric (fun (x: int16, i, a) -> Stream.write(x, i, a)) x s
    static member format (x, s) = 
           formatGeneric (fun (x: string, i, a) -> Stream.write(x, i, a)) x s

请注意,
Stream.write
是以完整形式编写的,并且对
x的类型进行了注释,以选择合适的重载。

这似乎更合适。有没有一种方法可以在不装箱x的情况下执行此操作?这是一个好问题。。。你写这篇文章的方式看起来更像是一个OO程序,而不是一个函数程序。T0yv0在这里使用了一个类型字典来存储序列化函数,但他肯定每个类型都有一个序列化函数:这似乎更合适。有没有一种方法可以不用装箱x来完成它?这是一个好问题。。。你写这篇文章的方式看起来更像是一个OO程序,而不是一个函数程序。这里的T0yv0使用了一个类型字典来存储序列化函数,但他肯定每个类型都有一个序列化函数:非常感谢你的解释和建议的替代方法!非常感谢您的解释和建议的替代方式!