F# 4.5.0.0:编译错误:FS1198、FS0661 和 FS0001:我正在调整从 C# 到 F# 的接口
F# 4.5.0.0: Compilation errors: FS1198, FS0661 and FS0001: I'm adapting a interface from C# to F#
我的目标是将 FSharp.Core 版本 4.5.0.0 移植到 .NET 4.0。为了实现我的目标,我正在用 F# 重写 Theraot.Core 的部分内容,因为 FSharp.Core 没有 "accept" 第三方库:https://github.com/theraot/Theraot/issues/121.
我正在调整从 C# 到 F# 的接口。
输入 F#:
namespace System.Collections.Generic
open Microsoft.FSharp.Core
type IReadOnlyCollection<'T> =
inherit IEnumerable<'T>
abstract Count : int with get
type IReadOnlyDictionary<'TKey, 'TValue> =
inherit IReadOnlyCollection<KeyValuePair<'TKey, 'TValue>>
abstract Keys : IEnumerable<'TKey> with get
abstract Values : IEnumerable<'TValue> with get
abstract Item : key : 'TKey -> 'TValue with get
abstract ContainsKey : key : 'TKey -> bool
abstract TryGetValue : key : 'TKey * [<System.Runtime.InteropServices.Out>] value : byref<'Value> -> bool
出现编译错误的地方:
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/map.fs#L626
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs#L88
在 C# 到 F# 中完美运行时,但从 F# 到 F# 出现编译错误:
map.fs:
FS1198 通用成员 'TryGetValue' 已在该程序点之前的非统一实例化中使用。考虑对成员重新排序,使该成员首先出现。或者,显式指定成员的完整类型,包括参数类型、return 类型和任何其他通用参数和约束。
FS0661 此绑定的一个或多个显式 class 或函数类型变量无法泛化,因为它们被限制为其他类型。
fslib-extra-pervasives.fs:
FS0001 此表达式应具有类型
''a'
但这里有类型
''T'
我也试过了,没成功:
abstract TryGetValue : key : 'TKey * [<System.Runtime.InteropServices.Out>] value : 'Value -> bool
编辑:
我正在迈出 F# 的第一步。我找到的唯一信息是F#的不变性很酷,但是有时候F#不能像C#一样写。
前两个编译错误不知从何而来,第三个是可以简化的:
namespace TestBugApplication1
open System.Collections.Generic
type DictImpl<'SafeKey,'Key,'T>(t : Dictionary<'SafeKey,'T>, makeSafeKey : 'Key->'SafeKey) =
interface IReadOnlyDictionary<'Key, 'T> with
member this.ContainsKey(key) = raise (System.NotImplementedException())
member this.Count = raise (System.NotImplementedException())
member this.GetEnumerator() = raise (System.NotImplementedException())
member this.GetEnumerator() = raise (System.NotImplementedException())
member this.Item
with get (key) = raise (System.NotImplementedException())
member this.Keys = raise (System.NotImplementedException())
member this.TryGetValue(key, r) =
match t.TryGetValue (makeSafeKey key) with
| false, _ -> false
| true, value ->
r <- value //<- Compiler error
true
member this.Values = raise (System.NotImplementedException())
我也可以发送下载 link 我正在编程的解决方案。
您的问题不在于实现,而在于 IReadOnlyDictionary
的定义。
abstract TryGetValue : key : 'TKey * [<Out>] value : byref<'Value> -> bool
请注意它是 'Value
。这意味着 TryGetValue
将具有 TryGetValue<V>(TKey key, out V value)
的签名而不是 TryGetValue(TKey key, out TValue value)
.
更正为
abstract TryGetValue : key : 'TKey * [<Out>] value : byref<'TValue> -> bool
将编译。
额外的错误是推理错误。如果您要实现重载成员,请注释类型以避免歧义。
member this.GetEnumerator() : IEnumerator<KeyValuePair<'Key, 'T>> =
raise (System.NotImplementedException())
member this.GetEnumerator() : IEnumerator =
raise (System.NotImplementedException())
我的目标是将 FSharp.Core 版本 4.5.0.0 移植到 .NET 4.0。为了实现我的目标,我正在用 F# 重写 Theraot.Core 的部分内容,因为 FSharp.Core 没有 "accept" 第三方库:https://github.com/theraot/Theraot/issues/121.
我正在调整从 C# 到 F# 的接口。
输入 F#:
namespace System.Collections.Generic
open Microsoft.FSharp.Core
type IReadOnlyCollection<'T> =
inherit IEnumerable<'T>
abstract Count : int with get
type IReadOnlyDictionary<'TKey, 'TValue> =
inherit IReadOnlyCollection<KeyValuePair<'TKey, 'TValue>>
abstract Keys : IEnumerable<'TKey> with get
abstract Values : IEnumerable<'TValue> with get
abstract Item : key : 'TKey -> 'TValue with get
abstract ContainsKey : key : 'TKey -> bool
abstract TryGetValue : key : 'TKey * [<System.Runtime.InteropServices.Out>] value : byref<'Value> -> bool
出现编译错误的地方: https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/map.fs#L626 https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs#L88
在 C# 到 F# 中完美运行时,但从 F# 到 F# 出现编译错误:
map.fs:
FS1198 通用成员 'TryGetValue' 已在该程序点之前的非统一实例化中使用。考虑对成员重新排序,使该成员首先出现。或者,显式指定成员的完整类型,包括参数类型、return 类型和任何其他通用参数和约束。
FS0661 此绑定的一个或多个显式 class 或函数类型变量无法泛化,因为它们被限制为其他类型。
fslib-extra-pervasives.fs:
FS0001 此表达式应具有类型
''a'
但这里有类型
''T'
我也试过了,没成功:
abstract TryGetValue : key : 'TKey * [<System.Runtime.InteropServices.Out>] value : 'Value -> bool
编辑: 我正在迈出 F# 的第一步。我找到的唯一信息是F#的不变性很酷,但是有时候F#不能像C#一样写。
前两个编译错误不知从何而来,第三个是可以简化的:
namespace TestBugApplication1
open System.Collections.Generic
type DictImpl<'SafeKey,'Key,'T>(t : Dictionary<'SafeKey,'T>, makeSafeKey : 'Key->'SafeKey) =
interface IReadOnlyDictionary<'Key, 'T> with
member this.ContainsKey(key) = raise (System.NotImplementedException())
member this.Count = raise (System.NotImplementedException())
member this.GetEnumerator() = raise (System.NotImplementedException())
member this.GetEnumerator() = raise (System.NotImplementedException())
member this.Item
with get (key) = raise (System.NotImplementedException())
member this.Keys = raise (System.NotImplementedException())
member this.TryGetValue(key, r) =
match t.TryGetValue (makeSafeKey key) with
| false, _ -> false
| true, value ->
r <- value //<- Compiler error
true
member this.Values = raise (System.NotImplementedException())
我也可以发送下载 link 我正在编程的解决方案。
您的问题不在于实现,而在于 IReadOnlyDictionary
的定义。
abstract TryGetValue : key : 'TKey * [<Out>] value : byref<'Value> -> bool
请注意它是 'Value
。这意味着 TryGetValue
将具有 TryGetValue<V>(TKey key, out V value)
的签名而不是 TryGetValue(TKey key, out TValue value)
.
更正为
abstract TryGetValue : key : 'TKey * [<Out>] value : byref<'TValue> -> bool
将编译。
额外的错误是推理错误。如果您要实现重载成员,请注释类型以避免歧义。
member this.GetEnumerator() : IEnumerator<KeyValuePair<'Key, 'T>> =
raise (System.NotImplementedException())
member this.GetEnumerator() : IEnumerator =
raise (System.NotImplementedException())