Reputation: 13
is it possible to have the same operator in a type definition work with different types on the right-hand side of the operator?
Definition of the |== operator via name plugElts compiles fine, but using it later in module RemoverTest fails with error FS0002: This function takes too many arguments, or is used in a context where a function is not expected
when function is supplied on the right-hand side.
module SampleOperators =
let inline (|==) (x: ^URel) (wires: ^Wires) =
(^URel: (static member plugElts: ^URel * ^Wires -> 'R) (x, wires))
module Remover =
open SampleOperators
type RemGroup<'G> = RemGroupPass | RemGroupAll | RemGroupExcept of 'G | RemGroupElts of 'G
type RemMap<'K,'P when 'K: comparison> =
RemGroup<Map<'K,'P>>
type RemFun<'K,'P when 'K: comparison> =
'K * 'P -> bool
type Rem<'K,'MapVal,'FunVal when 'K:comparison> =
| Map_ of RemMap<'K,'MapVal>
| Fun_ of RemFun<'K,'FunVal>
type X<'K,'P when 'K:comparison> =
{ id: 'K
vv: Rem<'K,'P,'P> }
static member inline plugElts (x:X<_,_>, ws:('K * 'P) seq) =
{x with vv = Map_ (RemGroupElts (Map.ofSeq ws))}
static member inline plugElts (x:X<_,_>, i:int) =
{x with vv = Map_ (RemGroupElts (Map.ofSeq [i,i]))}
static member inline plugElts (x:X<_,_>, fn:('K * 'P -> bool)) =
{x with vv = Fun_ fn}
module RemoverTest =
open Remover
open SampleOperators
let xxx1 () =
{id = 1; vv = Map_ RemGroupPass} |== [1,1] // compiles ok
let xxx2 () =
{id = 1; vv = Map_ RemGroupPass} |== 1 // compiles ok
let xxx3 () =
({id = 1; vv = Map_ RemGroupPass}:X<_,_>) |== (fun _ -> bool) // can't compile
Are there ways to make this work without wrapping the right-hand side in discriminated union?
Thanks, Karol
edit: added overload for right-hand side with int type which works fine
Upvotes: 1
Views: 91
Reputation: 3149
The moment you invoke the operator in xxx3
you need to provide an actual function - what you have there right now is only the equivalent of a type declaration. Change to the following, and it will compile:
let xxx3 () =
({id = 1; vv = Map_ RemGroupPass}:X<_,_>) |== (fun _ -> true)
Here's a more compact version of your question:
type MoreFun<'T> = 'T -> int
type X<'T> =
{
B: int
F: MoreFun<'T>
}
static member (|==) (a: X<_>, b: int) = { B = b; F = fun (f:int) -> b}
static member (|==) (a: X<_>, b: MoreFun<_>) = { a with F = b }
module Tests =
let one (f: int) = 1
let t1() = { B = 1; F = one } |== 2
// let t2() = { B = 1; F = one } |== (fun _ -> int) // Does not work
let three: MoreFun<_> = (fun _ -> 3)
let t3() = { B = 1; F = one } |== three
// You don't need to cast three to be of type MoreFun:
let t4() = { B = 1; F = one } |== (fun _ -> 3)
Upvotes: 2