简体   繁体   中英

How to collapse a match on a discriminated union in F#

How does one take the results of a function that returns object, and cast it to a discriminated union in F#?

Problem scenario, I'm working with the javascript executor on a webdriver in selenium. The docs specify that the output should be an object of the certian types or list of types. (Ref https://www.w3.org/TR/webdriver/#executing-script )

I'd like to give the returning object some structure by casting it into a discriminated union so I can match on it later.

Casting directly doesn't work and union types aren't allowed to have constructors so I can't exactly drop it in there either. What's the proper way of going about this?

type JsResult = 
    | E of IWebElement
    | I of Int64
    | B of bool
    | S of String
    | LE of IWebElement list
    | LI of Int64 list
    | LB of bool list
    | LS of String list
    | N of Object
    override self.ToString () =
        match self with 
        | E e -> e.Text
        | I i -> i.ToString()
        | B b -> b.ToString() 
        | S s -> s
        | LE le -> String.concat " " (le |> Seq.map(fun x-> x.Text))
        | LI li -> String.concat " " (li |> Seq.map(fun x-> x.ToString()))
        | LB lb -> String.concat " " (lb |> Seq.map(fun x-> x.ToString()))
        | LS ls -> String.concat " " ls
        | N _ -> String.Empty

let execute script : JsResult = (browser :?> IJavaScriptExecutor).ExecuteScript(script) :> JsResult

Maybe create a static factory method? Try this:

type JsResult = 

    // ...

    with static member ofObject o =
        match box o with
        | :? IWebElement as e -> E e
        | :? Int64 as i -> I i
        | :? bool as b -> B b
        | :? String as s -> S s
        | :? (IWebElement list) as le -> LE le
        | :? (Int64 list) as li -> LI li
        | :? (bool list) as lb -> LB lb
        | :? (String list) as ls -> LS ls
        | :? Object as n -> N o
        | _ -> failwith "No wrapper available for type"


let execute script : JsResult = (browser :?> IJavaScriptExecutor).ExecuteScript(script) |> JsResult.ofObject

(The boxing is only needed if any of the specified type is a value type like int, or bool).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM