这是一个延伸F# Recursive Tree Validation的问题,我昨天很好地回答了这个问题。
此问题涉及在现有树中插入子项。这是我想要使用的更新类型:
type Name = string
type BirthYear = int
type FamilyTree = Person of Name * BirthYear * Children
and Children = FamilyTree list
我的最后一个问题是关于检查树的有效性,这是我决定采用的解决方案:
let rec checkAges minBirth = function
| Person(_,b,_) :: t -> b >= minBirth && checkAges b t
| [] -> true
let rec validate (Person(_,b,c)) =
List.forall isWF c && checkAges (b + 16) c
现在我希望能够以下列形式插入一个Person Simon 作为特定Person Hans 的孩子
insertChildOf "Hans" simon:Person casperFamily:FamilyTree;;
因此,输入应为父 name , child 和 family tree 。理想情况下,它应该返回一个修改后的族树,即 FamilyTree选项
我正在努力的是合并验证函数以确保它是合法的,并且如果插入Person已经是父级,则可以将其正确地插入到子级列表中 - 可能作为单独的函数。 / p>
欢迎所有帮助,非常感谢 - 谢谢! :)
答案 0 :(得分:3)
在您发表评论之后,代码将按预期运行:
let insert pntName (Person(_, newPrsnYear, _) as newPrsn) (Person (n,y,ch)) =
let rec ins n y = function
| [] -> if y < newPrsnYear && n = pntName then Some [newPrsn] else None
| (Person (name, year, childs) as person) :: bros ->
let tryNxtBros() = Option.map (fun x -> person::x) (ins n y bros)
if y < newPrsnYear && n = pntName then // father OK
if newPrsnYear < year then // brother OK -> insert here
Some (newPrsn::person::bros)
else tryNxtBros()
else // keep looking, first into eldest child ...
match ins name year childs with
| Some i -> Some (Person (name, year, i) :: bros)
| _ -> tryNxtBros() // ... then into other childs
Option.map (fun x -> Person (n, y, x)) (ins n y ch)
在我之前的回答中,我一直避免使用List函数,因为除非树提供遍历,否则我认为它们不适合树结构。
在使用List函数(使用lambdas和combinators)或纯递归的意义上,我可能有点纯粹,但总的来说,我不喜欢混合它们。