6

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

Community
  • 1
  • 1
NoIdeaHowToFixThis
  • 4,484
  • 2
  • 34
  • 69

3 Answers3

9

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
kaefer
  • 5,491
  • 1
  • 15
  • 20
4

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
NoIdeaHowToFixThis
  • 4,484
  • 2
  • 34
  • 69
polkduran
  • 2,533
  • 24
  • 34
2

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>.

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • s/declare a *value* nullable/declare a value optional/ ? – Ruben Bartelink Mar 06 '14 at 10:59
  • Either I misread the original question, or made some other cognitive error along the way, but I ended up thinking this was the solution. Obviously, the right answer is the one provided by polkduran, but I thought I'd just leave my answer here, in the off chance it could ever help someone else... – Mark Seemann Mar 06 '14 at 11:40
  • 1
    @Mark The `?arg` syntax in F# does not "make a value nullable". It declares an element of a tupled method parameter as optional for F# clients. However, non-F# clients will see it as `FSharpOption<...>`. This is different from the `?Type` syntax in C#, which declares a value type as nullable, which appears to all CLI clients, including F#, as `Nullable<...>`. The two concepts have nothing to do with each other... – Marc Sigrist Mar 06 '14 at 16:48
  • @MarkSeemann Yes, makes sense - esp with the context. +1 as it [with the explanation] adds variety without misleading. – Ruben Bartelink Mar 06 '14 at 22:55