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

时间:2016-02-20 20:34:59

标签: f#

我创建了一个简单的函数,它将签名'a -> 'b -> 'c option的常见F#函数包装到更符合C#的&#34;功能为:'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

违规行为f cRef

2 个答案:

答案 0 :(得分:5)

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

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

原因是您的wrapOptionF需要byref个参数。但是,byref<int>实际上不是intint ref这样的类型 - 它只是向编译器指示您的参数应该通过引用传递(例如C#中的out )。但是,进入您的函数后,您所拥有的是常规int

修改:请注意,智能感知会将cRef显示为byRef<int>类型。但是,如果您将另一个变量绑定到cRef,您会看到所获得的类型是常规int。您可以将此行放在TryDivide内,然后将鼠标悬停在a上以查看它:

let a = cRef

使用&运算符告诉编译器您通过引用将cRef传递给f - 这正是f所需要的 - 使类型系统满意。我使用C#项目对此进行了测试,TryDivideWrapper.TryDivide(a, b, out c)按预期工作。加入@MarkSeemann的tryDivide你应该很高兴。

答案 1 :(得分:1)

我不确定我理解原因,但这似乎有效:

fun File.copyInputStreamToFile(inputStream: InputStream) {
    inputStream.use { input ->
        this.outputStream().use { fileOut ->
            input.copyTo(fileOut)
        }
    }
}

顺便说一句,OP type TryDivideWrapper() = static member TryDivide(a, b, [<Out>]cRef:byref<int>) : bool = wrapOptionF tryDivide a b &cRef 实现会在tryDivide上引发异常。这是一个有效的替代实现:

tryDivide 1 0

FSI:

let tryDivide (a:int) (b:int) =
    if b = 0
    then None
    else Some (a / b)