Как построить общий случай объединения в цитате F#?

Следующий код не работает:

open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Quotations
let (empty,cons) =
    FSharpType.GetUnionCases(typeof<List<_>>)
    |> (fun cases ->
        cases |> Array.find (fun c -> c.Name = "Empty"),
        cases |> Array.find (fun c -> c.Name = "Cons"))

let valuesToList values =
    values
    |> List.map (fun v -> Expr.Value(v))
    |> List.fold
        (fun l v -> Expr.NewUnionCase(cons, [v;l]))
        <@@ List.empty<int> @@>

[1;2;3]
|> valuesToList

с исключением:

System.ArgumentException: Type mismatch when building 'sum': incorrect argument type for an F# union. Expected 'System.Object', but received type 'System.Int32'.

Как указать общий тип параметра для случая Cons union?


person mavnn    schedule 20.05.2015    source источник


Ответы (1)


Проблема с GetUnionCases(typeof<List<_>>). Подстановочный знак выводится как obj. Таким образом, ошибка

Ожидается «System.Object», но получен тип «System.Int32».

Вот рабочая версия.

let valuesToList (values: list<'a>) =
    let empty, cons =
        FSharpType.GetUnionCases(values.GetType())
        |> (fun cases ->
            cases |> Array.find (fun c -> c.Name = "Empty"),
            cases |> Array.find (fun c -> c.Name = "Cons"))
    values
    |> List.map Expr.Value
    |> List.fold
        (fun l v -> Expr.NewUnionCase(cons, [v;l]))
        <@@ List.empty<'a> @@>
person Daniel    schedule 20.05.2015
comment
Верно. Я в контексте поставщика типов: D - person mavnn; 20.05.2015
comment
Но эта вторая перегрузка Value вполне может сработать. - person mavnn; 20.05.2015
comment
Затем вам нужно будет упаковать элементы списка: [box 1; box 2; box 3] - person Daniel; 20.05.2015
comment
К сожалению, это скорее разрушит смысл упражнения для меня. Возможно, мне придется использовать что-то еще, а не список. Спасибо за помощь. - person mavnn; 20.05.2015
comment
Мое объяснение проблемы было неверным. Исправлено. - person Daniel; 20.05.2015
comment
Интересный. Конечно, поскольку предоставляется 'a, это не будет известно во время компиляции. Я думаю, что немного магии отражения может помочь. - person mavnn; 20.05.2015