简体   繁体   中英

unclear about a type error; the ide knows the type, the compiler doesn't, in F#

I have the following code:

override this.GetDocumentHandlers() =
    Map [
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            (fun x ->
                use ms = new MemoryStream(x)
            ...

and I get the following error:

[FS0041] A unique overload for method 'MemoryStream' could not be determined based on type information prior to this program point. A type annotation may be needed.
Known type of argument: 'a
Candidates:
 - MemoryStream(buffer: byte []) : MemoryStream
 - MemoryStream(capacity: int) : MemoryStream

The IDE shows me it knows the type:

在此处输入图片说明

and it is byte[]

This method is used like this:

core.GetDocumentHandlers() |> Map.iter (fun k v -> terminal.RegisterDocumentHandler(k, v))

with:

member this.RegisterDocumentHandler (mimeType: string, handler: byte[] -> unit) =
    documentHandlers.[mimeType] <- handler

so the type appears clear to me.

I thought I could cast to avoid the problem (although I really want to understand what the problem is)

and I did:

new MemoryStream(x :> byte[])

but then I get:

[FS0059] The type 'byte []' does not have any proper subtypes and need not be used as the target of a static coercion

If I do this:

let doNothing bytes : byte[] = bytes
use ms = new MemoryStream(doNothing x)

then it works...

What am I missing?

First, when the compiler encounters an overloaded method of constructor, it needs to be able to resolve which overload this is based on information that it has about types from earlier. In your case, there is no type hint that would help it, so it fails. You can fix that by adding a type annotation, eg on the lambda function:

override this.GetDocumentHandlers() =
    Map [ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
          (fun (x:byte[]) ->
                use ms = new MemoryStream(x)
                .... )

There are other places where you could put the annotation - eg on the return type of the GetDocumentHandlers method. However, this has to come before the overload.

Second, why does the IDE still show the right inferred type and the compiler does not accept the code? The way the F# type checking works is that it proceeds from left to right - in an IDE, the compiler tries to recover from any error by making a "best guess" so that it can continue and give you auto-complete and other hints, even for incomplete programs. This guess can sometimes be wrong though. This is acceptable for an IDE, but would not be acceptable in the actual compiler. So, here, you're seeing a case where the compiler running in the IDE-mode makes a good guess.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM