F# 5.0の新機能 その2

F# Advent Calendar 2020の1日目の記事であるF# 5.0の新機能で大体書かれているのですが、2つ抜けているものがあるので紹介します。

nameofパターン

RFC FS-1085

nameof の値でパターンマッチできます。

RFCにはタグを nameof で取り出しておいて、それを元にデシリアライズする例が載っています。

// 使う型

type RecordedEvent = { EventType: string; Data: byte[] }

type MyEvent =
  | A of AData
  | B of BData
// シリアライズ用関数

let serialize (e: MyEvent) : RecordedEvent =
  match e with
  | A adata -> { EventType = nameof A; Data = JsonSerializer.Serialize<AData>(adata) }
  | B bdata -> { EventType = nameof B; Data = JsonSerializer.Serialize<BData>(bdata) }
// デシリアライズ用関数

let deserialize (e: RecordedEvent) : MyEvent =
  match e.EventType with
  | nameof A -> A (JsonSerializer.Deserialize<AData>(e.Data))
  | nameof B -> B (JsonSerializer.Deserialize<BData>(e.Data))
  | t -> failwithf "Invalid EventType: %s" t

地味に便利ですね。

string関数の実装変更

RFC FS-1089

string は今まで静的に解決される型パラメーターを取るinline関数だったのですが、F#5.0からは普通の型パラメーターを取るinline関数になります。 また、今までデッドコードだったコードを有効化し、より多くの型に対するケースを追加しています。

これは例を見てもらうとびっくりするかもしれません。

// 今まではエラーだったが、F#5.0からはエラーにならない
type Either<'L, 'R> =
  | Left of 'L
  | Right of 'R
  override this.ToString() =
    match this with
    | Left x -> string x
    | Right x -> string x

他にもフォーマットに "g" を指定したのを null に変更したりもしています。 diffを見てもらった方が分かりやすいかもしれません。