在玩了一些F#成员约束功能并编写如下函数之后:
let inline parse< ^a when ^a : (static member Parse: string -> ^a) > s =
(^a: (static member Parse: string -> ^a) s)
这很好用:
let xs = [ "123"; "456"; "999" ] |> List.map parse<int>
我正在尝试编写其他函数 tryParse
,它使用静态方法 TryParse
并将解析结果包装成 'a option
类型以便在F#中获得更好的支持 . 像这样的东西不编译:
let inline tryParse s =
let mutable x = Unchecked.defaultof< ^a>
if (^a: (static member TryParse: string * ^a byref -> bool) (s, &x))
then Some x else None
错误是:
错误FS0001:此表达式应该具有类型byref <'a>,但这里的类型为'a ref
F# ref
-cells也不起作用:
let inline tryParse s =
let x = ref Unchecked.defaultof< ^a>
if (^a: (static member TryParse: string * ^a byref -> bool) (s, x))
then Some x else None
我究竟做错了什么?
3 回答
UPDATE
这似乎在F#3.0中得到修复 .
Old answer:
我同意斯蒂芬的评论,认为这很可能是一个错误 . byref类型有许多限制,因此对我来说并不特别令他们不满意成员约束 . 这是使用反射的(丑陋)解决方法:
我认为这也是一个bug,有成员约束和byref类型 . 我可以通过更改成员约束的签名来制作稍微不那么难看的反射版本:
这个非常接近:
但是我得到一个错误FS0421:当我尝试编译它时,此时不能使用变量'x'的地址 .
这编译但仍然无法按预期工作:
在这个特定的情况下,而不是使用反射我只会在f#中重新创建Parse的TryParse