【问题标题】:Printing tree list tuple elements in F#在 F# 中打印树列表元组元素
【发布时间】:2014-10-19 22:18:27
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    或者如果你对尾巴完全不感兴趣:

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

    注意

    有助于澄清代码的内容:树是定义中的元组列表。如果您编写使元组的括号显式的模式会更好,我的意思是如果您编写:

    | 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
    

    【讨论】:

    • 我意识到我正在将元组与列表进行匹配,因此我删除了根元组并将整个电话簿作为问题更新中发布的列表。
    • 我试过 let listelements tree = tree |> List.iter (fun x -> match x with | Node((a, b)::_/xs) -> printf "%s" a) 但只有第一个节点被打印?
    • 不,这不是问题所在。您没有将元组与列表匹配。您正在将(单个)元组列表与(任意数量)元组列表进行匹配。问题还是一样,只需将模式更改为我建议的模式,它就会匹配。
    • 哦...好的,但是在运行时再次不匹配:|节点[(a, b)] -> printf "%A %A" a b
    • 当然。这只是为了澄清,但如果你想解决它,按照我从一开始就建议的那样添加列表的尾部:|节点((a, b)::xs)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2020-06-06
    相关资源
    最近更新 更多