Динамический поиск в F#

Может ли кто-нибудь помочь мне со статьей Томаса Петричека: http://tomasp.net/blog/fsharp-dynamic-lookup.aspx/#dynfslinks? Проблема в том, что он сильно устарел. Я понимаю, что пространства имен

open Microsoft.FSharp.Quotations.Typed
open Microsoft.FSharp.Quotations.Raw

ушли. Поэтому я убрал отверстия. Но ошибки все же есть. «Введено» не определено. «RecdGet» не определен. И я подозреваю, что они не последние. Я пытаюсь доказать своему боссу, что F# хорош для нормализации базы данных. Динамический поиск полей действительно помог бы мне разобраться с полями с одинаковыми именами и разными префиксами.

На fpish также есть пост Томаса: https://fpish.net/topic/None/57493, который, как я понимаю, предшествует статье


person alehro    schedule 17.02.2017    source источник
comment
Вы ищете что-то подобное? stackoverflow.com/questions/17640218/   -  person N_A    schedule 17.02.2017
comment
@mydogisbox, Да, но я хочу, чтобы доступ проверялся статически. Итак, если свойство не существует, я получаю ошибку компиляции. Насколько я понимаю, решение Томаса делает это.   -  person alehro    schedule 17.02.2017


Ответы (1)


Вот грубый эквивалент:

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

type DynamicMember<'t,'u> = Expr<'t -> 'u>

let getValueReader (expr:DynamicMember<'recdT, 'fieldT>) = 
  // Match the quotation representing the symbol
  match expr with
  | Lambda(v, PropertyGet (Some (Var v'), pi, [])) when v = v' ->
      // It represents reading of the F# record field..
      // .. get a function that reads the record field using F# reflection
      let rdr = Reflection.FSharpValue.PreComputeRecordFieldReader pi

      // we're not adding any additional processing, so we just
      // simply add type conversion to the correct types & return it
      ((box >> rdr >> unbox) : 'recdT -> 'fieldT)
  | _ -> 
      // Quotation doesn't represent symbol - this is an error
      failwith "Invalid expression - not reading record field!"

type SampleRec = { Str : string; Num : int }

let readStrField = getValueReader <@ fun (r : SampleRec) -> r.Str @>
let readNumField = getValueReader <@ fun (r : SampleRec) -> r.Num @>   

let rc = { Str = "Hello world!"; Num = 42 }
let s, n = readStrField rc, readNumField rc

printfn "Extracted: %s, %d" s n
person kvb    schedule 17.02.2017