Работа с Nullable <'T> в F # - PullRequest
       30

Работа с Nullable <'T> в F #

4 голосов
/ 10 сентября 2009

Мне интересно, что другие придумали для работы с Nullable <'T> в F #. Я хочу использовать Nullable <'T> для типов данных, чтобы сериализация работала правильно (т.е. не записывал тип опции F # в XML). Но я не хочу, чтобы мой код застрял, имея дело с уродством, связанным с Nullable <'T> напрямую. Какие-либо предложения?

Лучше ли использовать активные шаблоны для сопоставления непосредственно в Nullable, или просто конвертировать в опцию и использовать сопоставление «Некоторые / Нет»?

Кроме того, мне бы очень хотелось услышать идеи по поводу обращения с пустыми ссылками. Если я использую, скажем, «строковый параметр», то я получаю в завершение тип опции F #. Если нет, то я не могу отличить действительно необязательные строки от строк, которые не должны быть нулевыми.

Есть ли шанс, что .NET 4 воспользуется опцией <'T>, чтобы помочь? (Если это часть BCL, то мы можем увидеть лучшую поддержку для него ...)

1 Ответ

2 голосов
/ 12 сентября 2009

Как активные шаблоны, так и опции, хорошо сочетаются с сопоставлением шаблонов, но, похоже, при использовании активных шаблонов (т. Е. typeof и ??) ваш код будет потреблять больше тиков. Основной вопрос: как вы будете справляться со своими пустыми ссылками? В случае, если ваш код рассчитан на длинные цепочки, рекомендуется использовать монадический синтаксис:

type Maybe<'a> = (unit -> 'a option)

let succeed x : Maybe<'a> = fun () -> Some(x)
let fail : Maybe<'a> = fun () -> None
let run (a: Maybe<'a>) = a()
let bind p rest = match run p with None -> fail | Some r -> (rest r)
let delay f = fun () -> run (f ())

type MaybeBuilder() =
  member this.Return(x) = succeed x
  member this.Let(p,rest) = rest p
  member this.Bind(p,rest) = bind p rest
  member this.Delay(f) = delay f

let maybe = new MaybeBuilder()

let add (a:'a) (b:'a) =
  maybe {
    match TryGetNumericAssociation<'a>() with
    | Some v -> return (v.Add(a,b))
    | _ -> return! fail
  }

let add3 (a:'a) (b:'a) (c:'a) =
  maybe {
    let! ab = add a b
    let! abc = add ab c
    return abc
  }

> let r1 = add 1 2;;
val r1 : (unit -> int option)
> r1();;
val it : int option = Some 3
> let r2 = add "1" "2";;
val r2 : (unit -> string option)
> r2();;
val it : string option = None
> let r3 = add3 "one" "two" "three";;
val r3 : (unit -> string option)
> r3();;
val it : string option = None
...