2017-02-04 25 views
5

Моя цель - написать список пар имя/значение в DSL и сделать это доступным для чтения. Значения здесь могут быть int, float, string или список любого из этих типов.Как написать список (string * obj) без использования upcast

Я использую пары string * obj и передавая их функции, которая принимает (string * obj) list.

Необходимо ли написать список без повышения значения параметра obj ?.

let myfun (values:(string*obj) list) = 
    // Do something... 

// This is pretty ugly 
myfun ["Name", upcast "Freddie"; "Age", upcast 50] 

// This would be the ideal 
myfun ["Name", "Freddie"; "Age", 50] 

ответ

8

Программирование 101: если вы себя повторять то же самое снова и снова, пакет его для повторного использования, сделать его функцией. В вашем случае, функция будет родовым (т.е. принимать параметр любого типа) и сделать вентиляционное от параметра:

let pair name value = name, value :> obj 
myfun [pair "Name" "Freddie"; pair "Age" 50] 

Хм ... Не намного лучше, правда? Но подождите, мы еще не закончили! Теперь, когда у вас есть эта функция, вы можете дать ей более приятное имя, которое сделает его приятнее. Скажем, ==>:

let (==>) name value = name, value :> obj 
myfun ["Name" ==> "Freddie"; "Age" ==> 50] 

Если набор возможных типов известен заранее и относительно небольшой (как ваш вопрос, кажется, указывает), вы можете пойти на шаг дальше и проверку компилятора, которые используются только разрешенные типы , Чтобы сделать это, вам нужно использовать метод перегрузку, статический разрешенные ограничения типа и некоторые синтаксические фокусы:

type Casters() = 
    static member cast (v: string) = v :> obj 
    static member cast (v: float) = v :> obj 
    static member cast (v: int) = v :> obj 
    static member cast (v: string list) = v :> obj 
    static member cast (v: float list) = v :> obj 
    static member cast (v: int list) = v :> obj 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> obj) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 
+0

Спасибо, но ваша функция _pair_ дает мне _The статическое принуждение от типа» а в «Ь включает неопределенный тип на основе информации до этой программы point_. Вы не видите ту же ошибку? [tryfsharp] (http://www.tryfsharp.org/create/seankearon/file3.fsx) –

+2

Ошибка. Я скопировал ваш 'upcast' вместо правильного оператора upcast с фактическим типом. Исправил его сейчас. –

+0

Это мило, спасибо! –

2

Вашего мнение, что ваши ценности могут только иметь определенные указанные типы. Интересно, есть ли у вас конкретная причина использовать obj вместо разграниченного союза, который отлично подходит для этой задачи?

Я изменил ответ Федора использовать тип DU вместо obj:

type Value = 
    | Int  of int  | Float  of float  | String  of string 
    | IntList of int list | FloatList of float list | StringList of string list 

type Casters() = 
    static member cast v = Int v 
    static member cast v = Float v 
    static member cast v = String v 
    static member cast v = IntList v 
    static member cast v = FloatList v 
    static member cast v = StringList v 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> Value) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 

Преимущество этого подхода заключается в том, что теперь у вас есть тип проверено соответствие шаблона, когда доступ к значениям, и дон «т должен сделать небезопасное понижающее приведение в obj:

let myfun (values:(string*Value) list) = 
    values 
    |> List.map (fun (k, v) -> 
     match v with 
     | Int v -> k + ":" + string v 
     | String v -> k + ":" + v.Trim()) 
     // etc. 
    |> String.concat "\n" 

myfun ["Name" ==> "Freddie"; "Age" ==> 50] |> printfn "%s" 
//Name:Freddie 
//Age:50 
+0

Да, это очень хороший момент. Я делаю это в другом месте программы, вопрос, связанный с кодом, который включает DSL. –

 Смежные вопросы

  • Нет связанных вопросов^_^