Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

optional parameters in abstract class type signature

The Class:

type NotAbstract () = 
    member this.WithOptionalParameters (x, ?y) = 
        let y = defaultArg y 10
        x + y

has the following type signature:

type NotAbstract =
  class
    new : unit -> NotAbstract
    member WithOptionalParameters : x:int * ?y:int -> int
  end

However, this does not work:

[<AbstractClass>]
type AbstractExample () = 
    abstract WithOptionalParameters: int * ?int -> int /// Ouch...

type NotAbstract () = 
    inherit AbstractExample ()
    override this.WithOptionalParameters (x, ?y) = 
        let y = defaultArg y 10
        x + y

How to write the proper type signature in the abstract definition of a function with optional parameters? I did not find any hint here.

PS: I am aware that (similar) result could be achieved with polymorphism

like image 298
NoIdeaHowToFixThis Avatar asked Mar 06 '14 08:03

NoIdeaHowToFixThis


3 Answers

Declaring an argument as Option type doesn't really make the argument optional.

NotAbstract().WithOptionalParameters(2)
// This expression was expected to have type
//     int * Option<int>    
// but here has type
//     int    

The spec §8.13.6 has it:

In a signature, optional arguments appear as follows: static member OneNormalTwoOptional : arg1:int * ?arg2:int * ?arg3:int -> int

Naming your optional argument in the abstract member signature thus

[<AbstractClass>]
type AbstractExample () = 
    abstract WithOptionalParameters: int * ?y:int -> int      

type NotAbstract () = 
    inherit AbstractExample ()
    override this.WithOptionalParameters (x, ?y) = 
        let y = defaultArg y 10
        x + y

NotAbstract().WithOptionalParameters(42)  // val it : int = 52
like image 178
kaefer Avatar answered Sep 25 '22 19:09

kaefer


Optional parameters are compiled to Option types, use Option<int> instead of ?int:

[<AbstractClass>]
type AbstractExample () = 
    abstract WithOptionalParameters: int * Option<int> -> int      

type NotAbstract () = 
    inherit AbstractExample ()
    override this.WithOptionalParameters (x, ?y) = 
        let y = defaultArg y 10
        x + y
like image 20
polkduran Avatar answered Sep 23 '22 19:09

polkduran


This should work:

[<AbstractClass>]
type AbstractExample () = 
    abstract WithOptionalParameters: int * Nullable<int> -> unit

In F#, there's no syntactical sugar for nullable types, so although you can declare a value nullable with the ?y syntax, you can't do that for a type. Instead, you'll have to use Nullable<T>.

like image 41
Mark Seemann Avatar answered Sep 25 '22 19:09

Mark Seemann