2015-10-05 34 views
10

在Haskell,如果我有工會的列表類型這樣的價值觀:如何`對工會的構造模式匹配的.. in`

example :: [Either Int Char] 
example = [Left 3, Right 'b', Left 6, Left 9, Right 'c'] 

我可以用一個小「絕招」提取所有匹配一些特定模式的結果:

lefts :: [Int] 
lefts = [l | Left l <- example] 

但是,如果我嘗試將此轉換爲F#,我得到一個錯誤:

let lefts = [for Choice1Of2 l in example -> l] 
       ~~~~~~~~~~~~ 
Incomplete pattern matches on this expression. (...) 

這(它甚至可能比默默地忽略像Haskell這樣的值更好的行爲!),但是F#中的是否有一些方便的方式來提取(並匹配)與列表/列表中的特定模式匹配的所有值序列號

回答

16

在F#中,如果您不符合所有情況,您將在所有情況下收到警告。

所以,你可以寫與之相匹配的表達中這兩種情況下,但是你的例子,而不是內涵我會使用功能List.choose

let example = [Choice2Of2 3; Choice1Of2 'b'; Choice2Of2 6; Choice2Of2 9; Choice1Of2 'c'] 
List.choose (function (Choice1Of2 x) -> Some x | _ -> None) example 
// val it : char list = ['b'; 'c'] 

這個功能是非常方便的這些情況。

12

我認爲你可以使用F#列表中的表達式做最接近的事是這樣的:

let lefts example = 
    [ for e in example do 
     match e with Choice1Of2 l -> yield l | _ ->() ] 

如果我理解正確的Haskell代碼,|之後的部分被用於不只是作爲一個提取,也作爲過濾器 - 隱式跳過所有與模式不匹配的事物。

F#在列表表達式中沒有相同的概念,所以你必須更加詳細。在這裏,我們只是遍歷所有項目使用for,然後我們明確使用yield產生源列表中每個Choice1Of2的新值(我們只是跳過其他任何東西)。

根據你在做什麼,使用List.choose(如Gustavo的答案中提到的)可能會更容易。但是,上面可能是最接近你可以得到的Haskell的理解語法。