在F#中打印树列表元组元素

时间:2014-10-19 12:00:36

标签: f# f#-interactive c#-to-f#

我有一个像这样的简单树结构..

type Tree<'a,'b> = 
    | Node of list<'a * Tree<'a,'b>>
    | Leaf of 'b

let phonebook = Node["MyPhonebook",
                     Node["Work",
                          Node["Company1", Node["Employee1", Leaf("phone#")];
                               "Company2", Leaf("phone#")];
                          "Private",
                          Node["Family", Node["Brother", Leaf("phone#");]; "Sister", Leaf("phone#")]
                         ]
                    ]

我只是试图打印这本电话簿的根文件夹(工作,私人),但似乎不管我做什么......

let listelements tree =
    match tree with
    | Node[a, b] -> // OK - root node
        printfn "%s" a // OK - root folder name
        match b with
        //| _ -> printf "%A" b // OK - prints whole node
        | Node[a, b] -> printf "%A" a // Match failure!

listelements phonebook

之后我意识到我已经将元组与列表匹配,所以我尝试了一些不同的东西,但我再次遇到了错配。

let phonebook = [Node["Work",
                      Node["Company1", Node["Employee1", Leaf("phone#")];
                           "Company2", Leaf("phone#")];
                      "Private",
                      Node["Family", Node["Brother", Leaf("phone#");]; "Sister", Leaf("phone#")]
                     ]
                 ]

let listelements tree =
    for i in tree do
        match i with
        | Node[a, b] -> printf "%s" a // Match fail

let listelements tree =
    //tree |> List.iter (fun x -> printf "%A" x) // OK - prints nodes
    tree |> List.iter (fun x ->
        match x with
        | Node[a, b] -> printf "%A" a) // Match fail

我到底做错了什么?必须有一个更优雅和简单的方法来做到这一点。我来自C#,这让我疯了:P

1 个答案:

答案 0 :(得分:1)

您正在匹配List的单个元素(元组)的列表,因此在第一种情况下,该列表仅包含一个元素,并且它通过编译器警告您匹配不完整。 但是在第二个匹配中,列表包含两个元组,因此它失败了。

使用head :: tail模式,如下所示:

| Node((a, b)::xs)

或者如果你对尾巴根本不感兴趣:

| Node((a, b)::_)

注意

有助于澄清代码的东西:tree是定义中的元组列表。如果你编写模式使得元组的括号明确,那就更好了,我的意思是如果你写:

| Node[(a, b)] -> 

而不仅仅是

| Node[a, b] -> 

这里编译器理解这是一个元组,但人类可能不会,特别是如果它来自Haskell背景。

因此,编写括号可能会帮助您弄清楚问题是您再次匹配只有一个元组的列表。

<强>更新

如果您想使用List.iter打印所有元素:

let rec listelements tree =
    let printNode (a, b) = 
        printfn "%s" a
        listelements b
    match tree with
    | Leaf leaf         -> printfn "Leaf %s" leaf
    | Node(listOfNodes) -> List.iter printNode listOfNodes