從理論上講,你不能完全按照你想要做的做,但你可以非常接近它。你無法創建這樣的功能的原因是因爲靜態類型。
使用元組可以組合不同類型的值,但要確保類型安全,元組必須是固定大小的,並且必須知道每個元素的類型。
列表可以包含可變數量的元素,但正因爲如此,每個元素的類型必須相同。否則,你不能用靜態類型語言來處理它。
在動態類型化語言中,例如,您可以創建一個包含列表(A)和另一個列表(B)的列表的單個函數。然後,將B中的每個元素添加到A中的每個列表中,然後完成。您也可以在靜態類型語言中使用兩種方法:
- 您首先將列表中的每個元素轉換爲
object
。
- 您首先創建每種類型的歧視聯盟。
第一個想法意味着你需要大量的向下向上投射,這通常不是你想要的靜態類型語言。第二種方法可行,但您必須將每個列表轉換爲您的DU類型(您還需要創建DU),稍後您需要進行模式匹配。從技術上講,它只與一種更安全的方式相同。
另一種方法,那就是我推薦的應用程序的用法。一個應用程序實際上意味着你升級一個函數,所以函數的每個參數可以是一個選項,列表等。所以,你首先要創建一個apply
功能是這樣的:
let apply fs xs = [
for f in fs do
for x in xs do
yield f x
]
let (<*>) = apply
一旦你擁有這樣的功能,你可以寫這樣的事情:
[fun a b c d -> (a,b,c,d)]
<*> [1..5]
<*> ["a";"b"]
<*> [(0,0);(1,1)]
<*> [100;200]
這則返回一個包含列表:
[(1, "a", (0, 0), 100); (1, "a", (0, 0), 200); (1, "a", (1, 1), 100);
(1, "a", (1, 1), 200); (1, "b", (0, 0), 100); (1, "b", (0, 0), 200);
(1, "b", (1, 1), 100); (1, "b", (1, 1), 200); (2, "a", (0, 0), 100);
(2, "a", (0, 0), 200); (2, "a", (1, 1), 100); (2, "a", (1, 1), 200);
(2, "b", (0, 0), 100); (2, "b", (0, 0), 200); (2, "b", (1, 1), 100);
(2, "b", (1, 1), 200); (3, "a", (0, 0), 100); (3, "a", (0, 0), 200);
(3, "a", (1, 1), 100); (3, "a", (1, 1), 200); (3, "b", (0, 0), 100);
(3, "b", (0, 0), 200); (3, "b", (1, 1), 100); (3, "b", (1, 1), 200);
(4, "a", (0, 0), 100); (4, "a", (0, 0), 200); (4, "a", (1, 1), 100);
(4, "a", (1, 1), 200); (4, "b", (0, 0), 100); (4, "b", (0, 0), 200);
(4, "b", (1, 1), 100); (4, "b", (1, 1), 200); (5, "a", (0, 0), 100);
(5, "a", (0, 0), 200); (5, "a", (1, 1), 100); (5, "a", (1, 1), 200);
(5, "b", (0, 0), 100); (5, "b", (0, 0), 200); (5, "b", (1, 1), 100);
(5, "b", (1, 1), 200)]
如果您不想創建運營商<*>
您還可以編寫:
[fun a b c d -> (a,b,c,d)]
|> apply <| [1..5]
|> apply <| ["a";"b"]
|> apply <| [(0,0);(1,1)]
|> apply <| [100;200]
但我通常不鼓勵使用<|
。我更喜歡這個:
let ap xs fs = [
for f in fs do
for x in xs do
yield f x
]
[fun a b c d -> (a,b,c,d)]
|> ap [1..5]
|> ap ["a";"b"]
|> ap [(0,0);(1,1)]
|> ap [100;200]
你必須在飛行中創建的唯一一件事是第一線。一個將4,5,6,...個參數映射到元組的函數。
如果你想知道更多關於Applicatives,它是怎麼工作的,我已經寫了關於這個議題二博客,帖子:
http://sidburn.github.io/blog/2016/04/13/applicative-list http://sidburn.github.io/blog/2016/03/31/applicative-functors
其實是有一個'List.allPairs'功能F#4.1爲兩個列表執行此操作。我不認爲你可以開箱即用,但你可能想看看這個[Combinatorics library](https://www.nuget.org/packages/Combinatorics)。它可能仍然沒有做你想要的,雖然... – s952163
當你發現自己在查看可變大小的元組時,你很可能會將它們與列表混淆。 –