【问题标题】:I have a mutual recursion problem in f-sharp我在 f-sharp 中有一个相互递归问题
【发布时间】:2021-03-26 04:14:52
【问题描述】:

我在 F# 中有以下类型:

type Name = string;;
type Sex = 
    | M // male
    | F // female
type YearOfBirth = int;;
type FamilyTree = P of Name * Sex * YearOfBirth * Children
and Children = FamilyTree list;;

//here is an example:
let f1 = P("Larry",M,1920,[P("May",F,1945,[P("Fred",M,1970,[])]);P("Joe",M,1950,[P("Adam",M,1970,[])]);P("Paul",M,1955,[])])

我的任务是创建一个函数:find: Name -> FamilyTree -> returns (found name, sex, year, [List of the names of all their children]

我知道它与相互递归有关,但我不确定如何应用它。 这是我到目前为止写的:

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'

有谁知道我做错了什么?我知道类型有问题,但我不知道如何解决它。我可以使用我能得到的所有帮助,非常感谢!

【问题讨论】:

  • 如果你输入 annotate 你所有的功能,它会很容易弄明白。
  • 从函数开始 find 需要两个参数,但实现只需要一个(家谱)。
  • 一般提示:为递归类型添加一个 catamorphism 通常会有所帮助。在您的代码中,catamorphism 可以轻松地将当前节点的名称与请求匹配并返回一个选项,该选项将指示父节点停止搜索。

标签: functional-programming f#


【解决方案1】:

以下解决方案在 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

变量和类型名称是可读的,但与您的版本基本相同。不需要函数fstnfindCf1 变为 family_example 并重新格式化以提高可读性。

你可以从FSharpAnswers_by_RFreytag,分支StackOverflow_001_I_have_a_mutual_recursion_problem_in_f-sharp拉下这个解决方案的git repo。

如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 2017-01-01
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多