Example from Microsoft F# documentation doesn't compile - f#

MS documentation: Use interfaces to group related operations
type Serializer =
abstract Serialize<'T>: preserveRefEq: bool -> value: 'T -> string
abstract Deserialize<'T>: preserveRefEq: bool -> pickle: string -> 'T
If I copy and paste that into an fsx script or a dotnet-interactive notebook, I'll get a compiler error that says:
This construct is deprecated: ':' is not permitted as a character in operator names and is reserved for future useF# Compiler(35)
What changes would I need to make in order to fix this example?

I think just adding a space before the colon fixes it:
type Serializer =
abstract Serialize<'T> : preserveRefEq: bool -> value: 'T -> string
abstract Deserialize<'T> : preserveRefEq: bool -> pickle: string -> 'T
This might be a compiler bug.

Related

How to specify the result type for F# function's signature?

I am still somewhat new to F#, I see myself struggling with some function signatures when the compiler fails to infer the type properly. In the Following example the compiler believed that the function type for TryParsewas string -> string so I had to create this definition with the lambda on the right side.
type SocialAccount =
| FacebookAccount
| UnknownAccount
type SocialAccount with
static member TryParse:(string -> SocialAccount option) = fun s ->
match s with
| "FACEBOOK" -> Some FacebookAccount
| _ -> None
I find that lambda after the equal a little bit ugly and decoupling the arg names from the types makes it a bit unreadable I think. Also create a type for every single complex function makes crowded namespaces.
Isn't there really anyway to define a function and specify its return type? I am looking for something like the following code (which is incorrect):
static member TryParse:(s:string -> SocialAccount option) =
match s with
| "FACEBOOK" -> Some FacebookAccount
| _ -> None
All suggestions are welcome. Including creative ones.
You can put a type annotation for the return value at the end of the declaration line:
static member TryParse(s: string): SocialAccount option =
As an aside, static member X = fun ... -> is not equivalent to static member X(...) =. The former creates a property, rather than a method.

Why is this code not sufficiently generic or even better why is that even checked?

I get an error on the definition of ToBar
type Foo = {foo: string}
type Bar = {bar: string}
[<AbstractClass>]
type AbstractType< ^T> (fn: ^T -> Foo) =
member inline this.ToFoo (x: ^T) = fn x
abstract ToBar: string -> Bar
This is the error message
This code is not sufficiently generic.
The type variable ^T could not be generalized
because it would escape its scope.
Apart from the fact that (even after reading all other SO questions on this) I don't get what this error tries to tell me ... but it is totally stunning that ToBar which does not even use that type parameter is getting an error
This happens because ToBar is not inline, which is a requisite for using statically resolved type constraints. But it seems that you don't really need them, simple generics would be enough. So just replace ^T with 'T, and it will work fine:
[<AbstractClass>]
type AbstractType<'T> (fn: 'T -> Foo) =
member inline this.ToFoo (x: 'T) = fn x
abstract ToBar: string -> Bar
If you think about it a bit more, it only makes sense: an abstract member can't really make use of SRTC, because it's dispatched at runtime, and SRTC-types need to be known at compile time.
On a related note, even if you get rid of ToBar in an effort to keep SRTC, you'll hit the next error:
error FS1113: The value 'ToFoo' was marked inline but its implementation makes use of an internal or private function which is not sufficiently accessible
This can be fixed by making the type itself private:
type private AbstractType< ^T> (fn: ^T -> Foo) =
member inline this.ToFoo (x: ^T) = fn x
This will work, because the type won't be accessible from outside assemblies, and therefore won't need to expose its SRTC parameters.

Simulating higher-kinded polymorphism with Object Algebra's in F#

In the paper Streams à la carte: Extensible Pipelines with
Object Algebras Biboudis et al. outline a method of "emulating type-constructor ploymorphism" using object algebras.
I am trying to use this method to implement a higher-order example, similar to those described in Typed Tagless Final Interpreters, within F# and have the following:
type App<'f,'a> = interface end
type ExprSYM<'f,'a> =
abstract litInt: int -> App<'f,int>
abstract litBool : bool -> App<'f,bool>
abstract add : App<'f,int> -> App<'f,int> -> App<'f,int>
abstract gt : App<'f,int> -> App<'f,int> -> App<'f,bool>
abstract conj : App<'f,bool> -> App<'f,bool> -> App<'f,bool>
The section relating to Brand Freshness describes nesting a class inside a type constructor. My translation to F# looks like:
type Eval<'a> =
static member t = new obj()
static member prj (app : App<Eval.t,'a>) = app :> Eval<'a>
inherit App<Eval.t,'a>
However, I get the error The type 't' is not defined.
What is the correct way to write this in F#?
Using a nested class doesn't particularly buy you anything; as the authors say
In the Yallop and White technique for OCaml, this is ensured syntactically by the “freshness” of the brand, t, which is private to the type constructor. In Java, the property is ensured by convention: every subtype S of App has a locally defined brand t and no subtype of App<S.t, X> other than S exists.
so you can obtain the same result with a different convention in F# (which doesn't support nested classes or static members within interfaces). For example, you could create the subclass plus a separate marker class inside a module:
module Pull =
type t = class end
type Pull<'t> =
inherit App<t, 't>
let prj (app : App<t, 't>) = app :?> Pull<'t>
and then ensure that you don't use Pull.t elsewhere.

What would be the inferred type of my function here?

I am wondering why F# compiler allows the following
type MyMath() =
member this.Add a b = a + b
What would be the type of Add method and its arguments ? If I compiled this into the Library and try to use it in C# what types of arguments it is going to expect ?
Shouldn't the F# require you to explicitly specify types when it comes to Methods of classes ?
You can enter the code in F# interactive and see the inferred type yourself:
> type MyMath() =
member this.Add a b = a + b;;
type MyMath =
class
new : unit -> MyMath
member Add : a:int -> b:int -> int
end
Here, the compiler uses default type for the + operator which is int. The operator can be used with other types, but the inference uses int as the default. You can use type annotations, but you are not required to do that if you are happy with the inferred type.
In general, you can use type annotations in F# to specify types if you want to, but in many cases, the inferred type will be exactly what you want, so you do not have to make the code more verbose, if the inference behaves as expected.
Of course, if you were writing some library and wanted to be super careful about changing the API, then you might want to use type annotations (or you can add F# Interface file .fsi)
F# Interactive is your friend:
type MyMath =
class
new : unit -> MyMath
member Add : a:int -> b:int -> int
end

F# signature files - defining constructor parameters

I'm running into an error when creating a signature file for an F# script file which I can't quite work out.
To replicate, create a new F# class library and add a file, Test.fs:
namespace Signatures
open System
type Test (id : Guid, name : string) =
member this.Id = id
member this.Name = name
This will build fine. Then create a new signature file above it, Test.fsi:
namespace Signatures
open System
type Test =
new : (Guid * String) -> Test
member Id : Guid
member Name : String
This will now not build with the error Module 'Signatures' requires a value 'new : (Guid * String) -> Test (this is different to the error you get if the constructor signature is different in the two files). The only real documentation I can find on defining constructors in the signature file is MSDN and that deals with parameterless constructors.
If you hover over Test in the .fs file the constructor's signature matches the one in the .fsi file. I've also tried changing the constructor so that it is not implicit with no joy.
I'm using the VS2012 RC, and have tried .Net 4 and 4.5.
It's too long for a comment, so I post it as an answer.
Test's constructor receives two arguments as its parameters, not one argument which is a tuple. I admit that * between arguments looks confusing. But the signature Guid -> string -> Test is even worse than that. Constructors should get some inputs and produce a new type instance. Curried form and partial application don't make sense in the context of constructors.
I think the brackets help clarify here.
type Test (id : System.Guid, name : string) =
member this.Id = id
member this.Name = name
produces new : id:Guid * name:string -> Test while
type Test (tuple: System.Guid * string) =
let id, name = tuple
member this.Id = id
member this.Name = name
gives me new : tuple:(Guid * string) -> Test in an FSI session. I use F# 2.0/MonoDevelop 3.0 for the record.
Regarding creating type signatures, I usually send code into F# Interactive and copy produced signatures to fsi files to avoid mistakes. If the tooltips and F# Interactive show type signatures wrongly on VS2012 RC, you should report at fsbugs (at) microsoft (dot) com.
An extra pair of parens can be significant. Consider the following:
type T =
static member Add(x, y) = x + y
static member AddTuple((x, y)) = x + y
which, in C#, appear as
int Add(int x, int y)
int AddTuple(Tuple<int, int> arg)
Tangentially, you can't do something similar in a constructor:
type Test((id, name)) = class end //DOESN'T COMPILE
Since constructors already take arguments in tupled form you would expect 'a * 'b and ('a * 'b) to be different things. This is consistent with method syntax.
If anyone wants to explain why this works, I'd love to know but I just started fiddling with the syntax to see if I could get anything more revealing out of the compiler.
If I remove the brackets are the tuple, it compiles, i.e. change this:
new : (Guid * String) -> Test
To:
new : Guid * String -> Test

Resources