Can one define a function to tell whether an element was constructed from a given type constructor?

StackOverflow https://stackoverflow.com/questions/20171531

  •  04-08-2022
  •  | 
  •  

Question

I'm working in F#, and have a type T which is a discriminated union of several things:

type T =
  | A of string * int
  | B of int
  | C

If I have a T list, I may want to pull out the things that were constructed using A. It's easy to pattern match like this:

myList
|> List.filter (fun x -> match x with | A(_,_) -> true | _ -> false)

The embedded match is a bit verbose, and there's a minor maintenance hassle in keeping the number of underscores in sync with the definition of A. I'd really like a function like this:

let constructedFrom (type constructor) (t : T) : bool = something

myList
|> List.filter (constructedFrom A)

Is there a way to define this 'constructedFrom' function?

Was it helpful?

Solution

The embedded match is a bit verbose, and there's a minor maintenance hassle in keeping the number of underscores in sync with the definition of A.

You can save a few keystrokes using function keyword. You can also use _ as a pattern of ignoring everything (it doesn't mean you have to bind to a single value).

myList
|> List.filter (function A _  -> true | _ -> false)

In general, if you repeatedly write functions as above, you should define a few active patterns, one for each case:

let (|ACase|_|) = function 
    | A _ as x -> Some x 
    | _ -> None

myList |> List.choose (|ACase|_|)

Is there a way to define this 'constructedFrom' function?

There's no idiomatic way to do so. I think active patterns can remedy the problem most of time.

OTHER TIPS

You can simplify the match in your List.filter by using function instead of fun. function = fun x -> match x with.

myList
|> List.filter (function A(_,_) -> true | _ -> false)

I don't think there's a way (or at least a good way) to define your constructedFrom function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top