Functional programming 我在f-sharp中有一个相互递归问题
我在F#中有以下类型: 我的任务是创建一个函数:find:Name->FamilyTree->returns(查找姓名、性别、年份,[所有子女的姓名列表] 我知道它与相互递归有关,但我不确定如何应用它。 这是我到目前为止写的:Functional programming 我在f-sharp中有一个相互递归问题,functional-programming,f#,Functional Programming,F#,我在F#中有以下类型: 我的任务是创建一个函数:find:Name->FamilyTree->returns(查找姓名、性别、年份,[所有子女的姓名列表] 我知道它与相互递归有关,但我不确定如何应用它。 这是我到目前为止写的: let fstn (f:FamilyTree) = match f with |P(n,s,y,c) -> n let rec find n t = function |P(n1,s1,y1,cs) -> if n1=n then (
let fstn (f:FamilyTree) =
match f with
|P(n,s,y,c) -> n
let rec find n t = function
|P(n1,s1,y1,cs) -> if n1=n then (n1,s1,y1,List.map (fun x -> fstn x) cs)
else findC n cs
and findC n clist =
match clist with
|[] -> []
|c::cs -> if n = fstn c then find n c
else findC n cs
当我跑的时候
find "May" f1;;
我得到:
error FS0001: This expression was expected to have type
'Name * Sex * YearOfBirth * Name list'
but here has type
''a list'
有人知道我做错了什么吗?我知道类型有问题,但我不知道如何解决。我可以利用我能得到的所有帮助,非常感谢!以下解决方案在Visual Studio Pro 2019版本16.8.3中运行
// addressing: https://stackoverflow.com/questions/65307389/i-have-a-mutual-recursion-problem-in-f-sharp
open System
type Name = string
type Sex =
| M // male
| F // female
type YearOfBirth = int;;
type FamilyTree =
| Person of Name * Sex * YearOfBirth * Children
| Nothing
and
Children = FamilyTree list
//here is an example:
let family_example = [Person("Larry",M,1920,
[Person("May",F,1945,
[Person("Fred",M,1970,[])]);
Person("Joe",M,1950,
[Person("Adam",M,1970,[])]);
Person("Paul",M,1955,[])
]
)]
let rec find name ( familyTree_list : FamilyTree list) : FamilyTree =
match familyTree_list with
| (Person( try_name, _, _, _)::_) & (person::_) when name = try_name -> person
| (Person( _, _, _, children)::siblings) when (children <> [] || siblings <> []) ->
let depth_search_result = find name children
if Nothing <> depth_search_result then depth_search_result
else find name siblings
| _ -> Nothing
[<EntryPoint>]
let main argv =
printfn "%A" (find "May" family_example)
printfn "%A" (find "Joe" family_example)
printfn "%A" (find "no one" family_example)
0 // return an integer exit code
//寻址:https://stackoverflow.com/questions/65307389/i-have-a-mutual-recursion-problem-in-f-sharp
开放系统
类型名称=字符串
类型性别=
|M//男
|女
出生年份类型=int;;
类型FamilyTree=
|姓名*性别*出生年份*子女的人
|没什么
及
Children=家庭树列表
//以下是一个例子:
让家庭为例=[个人(“拉里”,M,1920,
[个人(“五月”),1945年5月6日,
[个人(“弗雷德”,M,1970,[]);
人(“乔”,男,1950年,
[个人(“亚当”,M,1970,[])];
个人(“保罗”,M,1955,[])
]
)]
让rec查找姓名(familyTree\u列表:familyTree列表):familyTree=
将familyTree\u列表与
|(当name=try\u name->Person时,Person(try\u name,u,u,u,u,u)::u)和(Person::u)
|(人(,,,,,孩子)::兄弟姐妹)当(孩子[]| |兄弟姐妹[])->
让深度搜索结果=查找名称子项
如果没有深度搜索结果,则深度搜索结果
否则会找到兄弟姐妹的名字
|什么都没有
[]
让主argv=
printfn“%A”(查找“May”系列\u示例)
printfn“%A”(查找“Joe”族\u示例)
printfn“%A”(查找“无人”族\u示例)
0//返回整数退出代码
变量名和类型名是可读的,但与您的版本基本相同。不需要函数fstn
和findC
。f1
变成了family\u示例
,并为可读性重新格式化
您可以从branchStackOverflow\u 001\u I\u f-sharp中存在相互递归\u问题\u取下此解决方案的git回购
如果您还有任何问题,请告诉我。如果您键入annotate所有函数,则很容易找到它。从函数开始,find需要两个参数,但实现只需要一个(FamilyTree).一般提示:为递归类型提供一个伴随选项通常会有所帮助。在您的代码中,预变形可以轻松地将当前节点的名称与请求匹配,并返回一个选项,该选项将向父节点发出停止搜索的信号。
// addressing: https://stackoverflow.com/questions/65307389/i-have-a-mutual-recursion-problem-in-f-sharp
open System
type Name = string
type Sex =
| M // male
| F // female
type YearOfBirth = int;;
type FamilyTree =
| Person of Name * Sex * YearOfBirth * Children
| Nothing
and
Children = FamilyTree list
//here is an example:
let family_example = [Person("Larry",M,1920,
[Person("May",F,1945,
[Person("Fred",M,1970,[])]);
Person("Joe",M,1950,
[Person("Adam",M,1970,[])]);
Person("Paul",M,1955,[])
]
)]
let rec find name ( familyTree_list : FamilyTree list) : FamilyTree =
match familyTree_list with
| (Person( try_name, _, _, _)::_) & (person::_) when name = try_name -> person
| (Person( _, _, _, children)::siblings) when (children <> [] || siblings <> []) ->
let depth_search_result = find name children
if Nothing <> depth_search_result then depth_search_result
else find name siblings
| _ -> Nothing
[<EntryPoint>]
let main argv =
printfn "%A" (find "May" family_example)
printfn "%A" (find "Joe" family_example)
printfn "%A" (find "no one" family_example)
0 // return an integer exit code