错误FS0001,此函数应具有类型byref <int>

Ove*_*ive 4 f#

我有一个做了一个简单的函数,它包装签名的共同F#的功能'a -> 'b -> 'c option更多的"C#兼容"功能:'a -> b -> byref<'c> -> bool.但不知何故,当我尝试在类中包装这样的方法时,我收到错误FS0001,我找不到错误.

代码如下

open System
open System.Runtime.InteropServices

// Given a function, f: 'a -> 'b -> 'c option returns
// A new function g: 'a -> 'b -> byref<'c> -> bool
let wrapOptionF f a b (g:byref<'c>) =
    match f a b with
    | Some v ->
        do g <- v
        true
    | None -> 
        false

let tryDivide (a:int) (b:int) =
    match Math.DivRem(a,b) with
    | v, 0 -> Some v
    | _ -> None

type TryDivideWrapper() =
    static member TryDivide(a, b, [<Out>]cRef:byref<int>) : bool =
        let f = wrapOptionF tryDivide a b
        f cRef
Run Code Online (Sandbox Code Playgroud)

违规行是f cRef.

小智 5

这篇文章包含更深入的解释,但简而言之,您可以使用以下内容替换最终的类型定义:

type TryDivideWrapper() =
    static member TryDivide(a, b, [<Out>]cRef:byref<int>) : bool =
        wrapOptionF tryDivide a b &cRef
Run Code Online (Sandbox Code Playgroud)

这样做的原因是你wrapOptionF需要一个byref参数.但是,byref<int>是不是真的喜欢一个类型intint ref-它只是一个指示,你的参数应该按引用传递(如编译器out在C#).但是,一旦进入你的功能,你所拥有的就是常规int.


编辑:请注意,Intellisense将显示cRef为具有类型byRef<int>.但是,如果将另一个变量绑定到cRef,则会看到您获得的类型是常规类型int.您可以将此行放入内部TryDivide,然后将鼠标悬停在上面a以查看它:

let a = cRef
Run Code Online (Sandbox Code Playgroud)

使用&运营商告诉您传递编译器cReff参照-这正是f需要-使得类型系统开心.我使用C#项目对此进行了测试,并按TryDivideWrapper.TryDivide(a, b, out c)预期工作.加入@MarkSeemann's tryDivide,你应该好好去.