wyer33
wyer33

Reputation: 6340

Trouble with a member constraint invocation expression when the member signature has type variables in F#

I'm having trouble using member constraint invocation expressions when the member signature has type variables. Specifically, the code

[<AutoOpen>]
module Foo

// Preapplied lens
type lens <'i,'j> = { get : 'j; set : 'j -> 'i }

// Record type with lenses 
type foo1 = {
    num_ : int;
    letter_ : char
} with
    member this.num = {
        get = this.num_;
        set = (fun num' -> {this with num_=num'})}
    member this.letter = {
        get = this.letter_;
        set = (fun letter' -> {this with letter_=letter'})}
end

let (foo1:foo1) = {num_ = 1; letter_ = 'a'}

// Another ecord type with lenses 
type foo2 = {
    num_ : int;
    name_ : string
} with
    member this.num = {
        get = this.num_;
        set = (fun num' -> {this with num_=num'})}
    member this.name = {
        get = this.name_;
        set = (fun name' -> {this with name_=name'})}
end

let (foo2:foo2) = {num_ = 2; name_ = "bob"}

// Add two to any record with the num lens
let inline add2 (x : ^t) =
    let num = (^t : (member num : lens<^t,int>) (x)) in
    num.get + 2

Gives the error:

test05.fsx(39,47): error FS0010: Unexpected symbol ) in expression

The issue is at the member constraint invocation expression on the second to last line. Basically, I can't figure out how to pass the type variables ^t and int to the lens type within the member constraint invocation expression. Is there a good way to accomplish this?

Upvotes: 2

Views: 98

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80714

There must be a space between < and ^ in the static constraint:

// Add two to any record with the num lens
let inline add2 (x : ^t) =
    let num = (^t : (member num : lens< ^t,int>) (x)) in
    num.get + 2

Otherwise, both characters <^ would be treated as a name of an infix function (aka "operator").

Upvotes: 3

Related Questions