🔍
Statically Resolved Type Parameters の地味な使いどころ
STRP; Statically Resolved Type Parameters(静的に解決される型パラメーター)の地味な使いどころを紹介します。
さっそくコードを。
open System.Collections
module Array =
let inline ofCollection (collection : 'Collection & #ICollection when 'Collection : (member Item : int -> 'Item with get)) =
let arr = Array.zeroCreate<'Item> collection.Count
collection.CopyTo(arr, 0)
arr
非ジェネリック版ICollection
はどんな型を保持しているか表面上は見えないです。
しかしその実装クラスは往々にして配列互換のためインデクサを定義していてます。つまりインデクサの戻り値を見れば保持している型を知ることができます。
ここでSTRPの出番です。「そんなメンバー定義があるんじゃろ?」として「その戻り値型を教えて?('Item
)」とできます。
結果、 Array.ofCollection : 'Collection -> 'Item[]
という配列への変換関数が作れます。
なお.NETの型定義では「そんなメンバー定義があるんじゃろ?」「その戻り値型を教えて?('Item
)」の部分が表現できないため、インライン展開が必須となり、F#言語以外からは呼び出すことができません。
使い方は次のようになります。
let matches = Regex.Matches(input, pattern) |> Array.ofCollection
これで、matches
は型ヒントなしでMatch[]
に変換されます。
この記事は概ね、Regex.Matches
の結果クラスMatchCollection
が(.NET Frameworkでは今なお)ICollection
しか実装していないことへの恨みで書かれています。
Discussion