【问题标题】:Recursive Union Type and List递归联合类型和列表
【发布时间】:2020-11-16 04:35:50
【问题描述】:

我从 F# 开始,我在 https://fsharpforfunandprofit.com/posts/fsharp-in-60-seconds// 上阅读了有关递归联合类型的信息

给出链接中的示例

type Employee =
  | Worker of Person
  | Manager of Employee list

如何创建Manager 类型的值并为其分配一个工人列表?

我可以像这样创建Worker 类型的值:

let john = {First = "John"; Last="Doe"}
let worker = Worker john

但我不知道如何创建 jane 类型的 Manager 值,并将 john 分配为 Empoyee 列表中的一项:

let jane =  { First="Jane"; Last="Doe" }
let manager = Manager [worker]

这可行,但我无法将 FirstLastjane 分配给 manager

在此示例中,经理是否意味着根本没有 First / Last

我必须如何更改 Manager 的类型定义才能同时拥有 Employee 的列表?

此外,Manager 似乎还没有成员 employees 我可以在创建 Manager 类型的值后访问?

【问题讨论】:

    标签: f#


    【解决方案1】:

    鉴于该类型定义,经理不能有名字/姓氏。类型定义不包含类似的内容。

    要使Manager 在这方面与Worker 工作类似,只需给它一个Person 值:

    type Employee = Worker of Person | Manager of Person * Employee list
    

    然后你可以创建一个经理简:

    let manager = Manager ({ First = "Jane"; Last = "Doe" }, [worker])
    

    对于employees的会员,有几句话要说。

    首先,远离会员。 F# 是功能优先的。函数比成员更好(出于我不打算在这里讨论的原因)。有一个功能:

    let employees emp = 
        match emp with
        | Manager (_, emps) -> emps
        | Worker _ -> ???  // what to return if the employee turned out to be worker?
    

    你马上就会发现一个困难:当员工是Manager时,当然,我们可以退回他们的员工。但是如果是Worker 呢?那要返回什么?

    一个合理的建议是返回一个空列表,因为毕竟Worker 没有任何员工为他们工作,对吧?

    let employees emp = 
        match emp with
        | Manager (_, emps) -> emps
        | Worker _ -> []
    

    另一种可能性是返回Option。哪种方法“正确”取决于您要如何处理结果,因此只有您可以回答。

    但如果你绝对坚持要有一个成员(请仔细想想你为什么需要它),你绝对可以像这样在你的类型中添加一个成员:

    type Employee = Worker of Person | Manager of Person * Employee list
        with
            member this.employees =
              match this with
              | Manager (_, emps) -> emps
              | Worker _ -> []
    

    【讨论】:

    • 实例成员实际上是一个接受实例的函数,但人体工程学略有不同。通常比静态成员或将函数放入同名模块中的等效方法更干净。由于您可以轻松地从一种转换到另一种,因此您做什么并不重要,最佳方法取决于未来的使用情况。
    • @CharlesRoddie 实际上,这两种方法并不相互排斥,您可以同时使用两种方法(F# 本身也是如此,您可以使用例如List.length xsxs.Length)。
    猜你喜欢
    • 1970-01-01
    • 2023-02-17
    • 2016-05-23
    • 2023-03-14
    • 1970-01-01
    • 2012-11-19
    • 2014-03-02
    • 2019-01-12
    • 1970-01-01
    相关资源
    最近更新 更多