How to downcast in F# while ignoring the generic types?

Viewed 101

Consider the following code with downcasting:

let list = [1; 2; 4] :> obj

// Successful
let list2 = list :?> int list

// Exception - System.InvalidCastException
let list3 = list :?> obj list
let list4 = list :?> _ list

Basically I want to downcast to a list collection but really ignore the generic type argument. However, it throws InvalidCastException exception for list3 and list4. Is there a way to achieve this?

As a context, I am trying to accept list of Linq expression for eager fetching from DBContext like this to address N+1 select problem for dependent entities within GraphQL queries. I cannot really downcast to a specific type. The expression must be downcasted to a generic version Expression<Func<Tenant,_>> within the loop:

let getTenants (db: Context) takeItems skipItems =


    let expr1 =
        <@ Func<_, _>(fun x -> x.TenantConfig) @>
        |> LeafExpressionConverter.QuotationToExpression


    let expr2 =
        <@ Func<_, _>(fun x -> x.Invitations) @>
        |> LeafExpressionConverter.QuotationToExpression

    // This list of includes expressions will be passed by the caller eventually
    let exprs = [expr1; expr2]


    let q =
        List.fold
            (fun (acc: IQueryable<Tenant>) (x: Expression) ->
                let expr = x :?> Expression<Func<Tenant, _>>
                acc.Include(expr) :> IQueryable<Tenant>)
            (db.Tenant.AsQueryable())
            exprs

    query {
        for tenant in q do
            skip skipItems
            take takeItems
            select tenant
    }
    |> fun x -> x.ToListAsync()
    |> Async.AwaitTask
    |> Async.map Seq.toList

I can use the string based version of IQueryable<'a>.Include but that tosses the type-safety completely out of window

0 Answers
Related