我想創建一個類型安全的遞歸函數來扁平化元組。 但是我不能讓下面的第一個遞歸級別的類型安全我如何編寫類型安全的遞歸內聯函數來扁平化元組
type Flatten = Flatten
with
static member inline ($) (Flatten, (a: 'a, b: 'b)) : 'x list =
List.concat [ Flatten.Flat a; Flatten.Flat b]
static member inline($) (Flatten, (a: 'a, b: 'b, c: 'c)) : 'x list =
List.concat [Flatten.Flat a; Flatten.Flat b; Flatten.Flat c]
static member inline Flat(x: obj) : 'x list =
match x with
| :? Tuple<'a, 'b> as t -> Flatten $ (t.Item1, t.Item2)
| :? Tuple<'a, 'b, 'c> as t ->Flatten $ (t.Item1, t.Item2, t.Item3)
| _ -> [x]
let inline flatten x = Flatten $ x
let a1 = flatten (1, (2, 2, 3), (3,3))
//this compiles
let a2 = flatten (1, (2, 2, 3, 4), (3,3))
// ^but this too
方面我嘗試另一種方法
type Flatten = Flatten
with
static member inline ($) (Flatten, (a: 'a, b: 'b)) = List.concat [ Flat $ a; Flat $ b]
static member inline ($) (Flatten, (a: 'a, b: 'b, c: 'c)) = List.concat [Flat $ a; Flat $ b; Flat $ c]
and Flat = Flat
with
static member inline ($) (Flat, a: 'a) = [a]
static member inline ($) (Flat, x: ('a *'b)) =
let (a, b) = x
List.concat [ Flatten $ a; Flatten $ b]
static member inline($) (Flat, x : ('a * 'b * 'c)) =
let (a, b, c) = x
List.concat [Flatten $ a; Flatten $ b; Flatten $ c]
let inline flatten x = Flatten $ x
let a = flatten (1, 1)
let a1 = flatten (1, 1, 3)
let a2 = flatten (1, 1, (3, 3))
,但我不能讓一個鍵入檢查。
有沒有人有線索?
一個額外的要求
我做這一切的原因,部分是因爲我想
let a1 = flatten (1, (2, 2, 3), (3,3))
產生
val a1 : int list
這是因爲,當我在喂int的元組的元組,那麼唯一明智的結果應該是int list
。 此刻我得到一個obj list
int第一個例子在第二個編譯錯誤。
此致
當然,你不能所有的元組大小。在某些時候,你必須指定儘可能多的重載元素。 – Gustavo
我只是放棄靜態鍵入保證並使用反射。 – scrwtp
@Gustavo - 由於F#只有元組大小1-8,並且「具有嵌套元組的更大元組大小」,所以我認爲實際上可以爲所有元組大小寫這個。不過,我從來沒有覺得有必要這樣做,因爲通常有更好的(恕我直言)解決方案來解決無論什麼問題都會導致你想要壓扁未知元組的元組。 – rmunn