type Title = string
type Document = Title * Element list
and Element = Par of string | Sec of Document;;
let s1 = ("Background", [Par "Bla"])
let s21 = ("Expressions", [Sec("Arithmetical Expressions", [Par "Bla"]);
Sec("Boolean Expressions", [Par "Bla"])])
let s222 = ("Switch statements", [Par "Bla"])
let s223 = ("Repeat statements", [Par "Bla"])
let s22 = ("Statements",[Sec("Basics", [Par "Bla"]) ; Sec s222; Sec s223])
let s23 = ("Programs", [Par "Bla"])
let s2 = ("The Programming Language", [Sec s21; Sec s22; Sec s23])
let s3 = ("Tasks", [Sec("Frontend", [Par "Bla"]);
Sec("Backend", [Par "Bla"])])
let doc = ("Compiler project", [Par "Bla"; Sec s1; Sec s2; Sec s3]);;
定义一个F#函数toc: Document → ToC
,该函数为文档生成目录。例如,该文档的前缀应带有编号的副标题,如下所示:
[([], "Compiler project");
([1], "Background");
([2], "The Programming Language");
([2;1], "Expressions");
([2;1;1], "Arithmetical Expressions");
([2;1;2], "Boolean Expressions");
([2;2], "Statements");
([2;2;1], "Basics");
([2;2;2], "Switch statements");
([2;2;3], "Repeat statements");
([2;3], "Programs");
([3], "Tasks");
([3;1], "Frontend");
([3;2], "Backend")]
答案 0 :(得分:0)
您的问题似乎遗漏了很多。例如:您认为哪些相互递归的辅助函数会对此有所帮助?
在我看来,这应该很简单,因为它只有一个递归函数。基本逻辑可以是:
[],title
。答案 1 :(得分:0)
您可以通过在序列表达式中遍历各节,保留当前节的编号并产生具有当前节号的所有标题来相对容易地做到这一点。
// Given the current level (as a list of numbers) and a list of elements,
// generate a list of headings in the elements and prepend `idx` indices
// to each heading that we generate
let rec generateToc idx elems = seq {
// We only care about nested sections, so this gets a list containing
// just sections and we later add number to them using `Seq.indexed`
let nested = elems |> Seq.choose (function
| Sec(title, elems) -> Some(title, elems) | _ -> None)
// For every nested section, we yield the title of the section and then
// recursively call `generateToc` to get the nested section titles
// (we append the current section number to `idx` when making the recursive call)
for i, (title, elems) in Seq.indexed nested do
yield List.rev (i+1::idx), title
yield! generateToc (i+1::idx) elems }
// To generate document TOC, we just yield the document title and
// then call `generateToc` on the document elements
let generateDocToc (title, elems) = seq {
yield [], title
yield! generateToc [] elems }
generateDocToc doc
|> Seq.iter (printfn "%A")