Search code examples
functional-programmingf#optional-parametersdiscriminated-union

F# Discriminated union with optional recurcive component


I'm working with F# and I struggle building my business model. Let's say I have a list of float and two types of transformations I can apply on it. By example:

type Transformation = | SMA of period:Period | P2MA of period:Period

Then I have defined a function let compute Transformation list to compute any kind of transformation over a list.

With the above Transformation type, I can create a SMA(3) or a P2SMA(5) by example.

I would like to be able to nest the transformations in a way I can write SMA(3, P2SMA(5, SMA(10))) by example. But also I would like to still be able to write SMA(2) only. I tried using options, but I think writing SMA(3, None) or SMA(3, Some(P2SMA(5))) is too verbose.

Is there any way to do that? Maybe my approach is wrong, as I'm new in F#, I may tackle the problem by the wrong way?

Thanks a lot for the help


Solution

  • Try my answer here.

    It's not possible to overload discriminated union cases in exactly the way you want. But if you'll accept a very slightly different syntax, you could do this instead:

    type Period = int
    
    type SmaTransform =
        | Sma of Period
        | Sma' of Period * Transform
    
    and P2smaTransform =
        | P2sma of Period
        | P2sma' of Period * Transform
    
    and Transform =
        | OfSma of SmaTransform
        | OfP2Sma of P2smaTransform
    
    let SMA(period) =
        Sma(period) |> OfSma
    
    let SMA'(period, transform) =
        Sma'(period, transform) |> OfSma
    
    let P2SMA(period) =
        P2sma(period) |> OfP2Sma
    
    let P2SMA'(period, transform) =
        P2sma'(period, transform) |> OfP2Sma
    
    let transforms =
        [|
            SMA(3)
            P2SMA(5)
            SMA'(3, P2SMA'(5, SMA(10)))
        |]
    
    for transform in transforms do
        printfn "%A" transform
    

    The only difference from your desired syntax is the apostrophe that denotes a nested transform.