Reputation: 1397
I'm looking into aether library and noticed this
type Lens<'a,'b> =
('a -> 'b) * ('b -> 'a -> 'a)
static member (^=) (Set, (_, s): Lens<'a,'b>) =
fun (b: 'b) ->
s b : 'a -> 'a
In the ^= function, b parameter if of type 'b in the lambda. However, in the lamda body, why is b type of 'a now?
Upvotes: 3
Views: 78
Reputation: 80915
I think you're just misreading the syntax. The code s b : 'a -> 'a
doesn't mean that b
is of type 'a
.
The right way to read it is to break it in two parts: the part before the colon is the expression, and the part after the colon is the type of that expression.
So the code s b : 'a -> 'a
actually means that s b
is of type 'a -> 'a
. It doesn't say anything about types of s
or b
individually.
Upvotes: 4
Reputation: 564861
However, in the lamda body, why is b type of 'a now?
It is not.
b
is an input which is typed 'b
, as shown in fun (b: 'b) ->
.
We can rewrite that member without the matches, and using a locally defined function, like so:
static member (^=) (Set, lens: Lens<'a,'b>) =
// Pattern match to extract out the 2nd portion of the lens, which is a function: 'b -> 'a -> 'a
let (_,s) = lens
// Define a function that takes a 'b and returns a new function of type: 'a -> 'a
let fn (b: 'b) : 'a -> 'a =
s b // this just partially applies s with the input "b"
fn // Return the function
Basically, the (Set, (_,s))
in the argument list binds "s" to the 2nd portion of a Lens<'a,'b>
, or a function typed ('b -> 'a -> 'a)
. Above, I've broken that out to be more explicit, and done this extraction in its own binding.
The member then returns a locally defined function (as a lambda). Above, I rewrote that using a let bound function, as it's often more clear.
Upvotes: 4