递归处理列表和列表子列表给出了类型不匹配

时间:2012-03-12 10:01:41

标签: list recursion f#

我尝试将分支图放入列表和子列表中 布局是

  • msg01
  • msg02
    • msg03
    • msg04
  • msg05

我想走分支图顶部 - >底部进入每个分支 但它失败了

  

错误类型不匹配。期待('a * 'b list) list,但给出'b list在统一“'a”和“'b * 'a list

时,结果类型将是无限的

有人能给我一些想法可以解决这个问题吗?

open System

let msgDiagram1 = [ ("msg03",[]); ("msg04",[]) ]
let msgDiagram = [ ("msg01", []); ("msg02", msgDiagram1); ("msg05",[]) ]      

let listToString lst =
    let rec loop acc = function
        | []    -> acc
        | x::xs -> let node = x
                   let sublst = snd(node)                      
                   if not ( sublst = List.empty ) then                        
                        loop "" sublst
                   else 
                        loop (acc + (string x)) xs

    loop "" lst

printfn "%A" (listToString msgDiagram)

1 个答案:

答案 0 :(得分:4)

由于msgDiagram1msgDiagram具有不同的类型,因此您无法在其上使用相同的loop函数。一个快速解决方法是在msgDiagram1上进行不同的处理:

let listToString lst =
    let rec loop acc = function
        | [] -> acc
        | (lbl, diag)::xs ->
            match diag with
            | [] -> loop (acc + string lbl + "\n") xs
            | _ ->
                let s = diag |> List.map (fun (label, _) -> "..." + label) 
                             |> String.concat "\n"
                loop (acc + string lbl + "\n" + s + "\n") xs
    loop "" lst

您为作业选择了错误的数据结构;因此,您不能代表超过2个级别的图表,并且这些级别被强制使用不同的类型。这里使用的正确工具是递归树数据结构:

type Diagram = Branch of string * Diagram list

现在可以使用相同类型Diagram list

定义上述值
let msgDiagram1 = [ Branch ("msg03",[]); Branch ("msg04", []) ]
let msgDiagram = [ Branch ("msg01", []); Branch ("msg02", msgDiagram1); 
                   Branch ("msg05", []) ]

listToString可以重写,以便在一个批处理中递归Diagram list