Search code examples
f#matchtuplesactive-pattern

F# match active pattern as expanded tuple


I get the following error in diff with a red squiggle under Subset.
Type mismatch. Expecting a Range -> Choice but given a Range * Range -> Choice

Is there some sort of type annotation I can add to the SubSet match so I don't have to use fst and snd? If not is there any intention to support this syntax?

type Range = {min : int64; max : int64}

let (|Before|After|BeforeOverlap|AfterOverlap|SuperSet|SubSet|) (x, y) = 
    if x.min > y.max then After
    elif x.min >= y.min then
        if x.max <= y.max then SubSet
        else AfterOverlap
    elif x.max < y.min then Before
    elif x.max <= y.max then BeforeOverlap
    else SuperSet

let useOldx x xe ye = ()

let diff (xe:IEnumerator<Range>) (ye:IEnumerator<Range>) =
    match xe.Current, ye.Current with
    | After as tuple -> ()
    | Before as t -> if xe.MoveNext() then useOldx (fst t) xe ye
    | SuperSet as t -> 
        let x, y = t
        if xe.MoveNext() then useOldx x xe ye
    | SubSet as x, y -> if xe.MoveNext() then useOldx x xe ye
    | _ -> ()

Solution

  • You could do this:

        | (x,y) & SubSet -> if xe.MoveNext() then useOldx x xe ye
    

    or you could do this:

    open System.Collections.Generic 
    
    type Range = {min : int64; max : int64}
    
    let (|Before|After|BeforeOverlap|AfterOverlap|SuperSet|SubSet|) (x, y) = 
        if x.min > y.max then After
        elif x.min >= y.min then
            if x.max <= y.max then SubSet(x,y)
            else AfterOverlap
        elif x.max < y.min then Before
        elif x.max <= y.max then BeforeOverlap
        else SuperSet
    
    let useOldx x xe ye = ()
    
    let diff (xe:IEnumerator<Range>) (ye:IEnumerator<Range>) =
        match xe.Current, ye.Current with
        | After as tuple -> ()
        | Before as t -> if xe.MoveNext() then useOldx (fst t) xe ye
        | SuperSet as t -> 
            let x, y = t
            if xe.MoveNext() then useOldx x xe ye
        | SubSet(x, y) -> if xe.MoveNext() then useOldx x xe ye
        | _ -> ()