strangelights.com

Main F# Site

Edit Edit
Print Print
Recent Changes Recent Changes
Subscriptions Subscriptions
Lost and Found Lost and Found
Find References Find References
Rename Rename
Search
List all versions List all versions
FSI Differences In Behaviour
.

Check out the formatting tips on the right for help formatting and making links.

Use the template below:

Summary

Pasting code into FSC line by line can reveal differences in the treatment of type inference. This is due to differences in the scope of type inference, and in particular the ValueRestriction. The scope of type inference for fsi is the chunks that are separated by ";;" terminators. The scope for fsc is an entire file.

For example, the following code compiles and runs just fine with fsc.exe

 open System
 open System.IO


 let realfun (f:> TextWriter) line = 
    f.WriteLine (line :> obj);;


 let newfun = realfun Console.Out;;


 let _ =
    newfun "newfun, realfun.";;

However, if stepping through in the top-level, fsi reports error when defining the function - newfun. Below is the error message.

 > let newfun = realfun Console.Out;;


 toplevel(2,4): error: FS0030: Type inference has inferred the signature
        val newfun : ('a -> unit)
 for 'newfun', but the definition of 'newfun' involves some computation, i.e.  
 it is not defined  as an immediate function. Either define 'newfun' as an  
 immediate, or add a type constraint to instantiate the type parameters.

This wouldn't matter except that languages like OCaml and F# cannot make all bindings as generic (polymorphic) as one might wish. This is called the "value restriction", and is covered in depth elsewhere, e.g. section 5.1.1 of http://www.cs.caltech.edu/courses/cs134/cs134b/book.pdf. This means that some type parameters can end up being unresolved unknowns, though by the end of a scope of type inference these must have been resolved.

The F# toplevel is a bit stricter than OCaml in this regard. In OCaml the toplevel is a single never-ending type inference scope, and the "newfun" binding one would have been assigned the type

        val newfun : ('_a -> unit)

where a represents an unresolved type inference variable, rather than a true generic type parameter. The subsequent binding then enforces the constraint 'a = string. F# cannot play this trick, because it cannot execute code without concrete values for type variables, due to the fact that it translates to .NET IL before execution, which is a typed intermediary language.

We don't think there's much we can do about this in the short term.

This means you will either have to paste across a larger chunk of your file or add a type annotation.

Some previous release of fsi saw small inconsistencies between fsi and fsc in this release, e.g. "open" declarations must be followed by a ";;".

These no longer occur.

Welcome to F Sharp Wiki, view the HomePage

This site supports the new NoFollow anti-spam initiative.

Recent Topics

Copyright 2005, Robert Pickering (Others where credited) | Terms of Use