联合中的通用参数

时间:2018-12-05 07:12:50

标签: f# ml

您好FSharpers(或任何MLer)

仍在尝试提高我的域建模技能(来自OOP)。假设我有以下内容

type A =
| AA of AA
| AB of AB

type AA = 
{ Code : 'a
  Time : 'b }

type AB =
{ Code : 'a
  Whatsoever : 'c }

现在让我们想象我想要以下函数签名:(A->'a)

据我目前的理解,我要解决的办法是

let f (a1:A) =
    match a1 with
    | AA a -> a.Code
    | AB a -> a.Code

此解决方案的不便之处在于,如果我要向A联合中添加一些新案例,则必须始终向其添加新案例。

我想象另一个解决方案将是元组类型的解决方案(但会丢失字段的“命名”):

type A =
| AA of AA * 'a
| AB of AB * 'a

type AA = 
{ Time : 'b }

type AB =
{ Whatsoever : 'c }

let f (a1:A) =
    snd a1

我错过了任何简单的解决方案吗? 谢谢!

2 个答案:

答案 0 :(得分:1)

此:

let f (a1:A) =  snd a1

将不起作用,因为要进入元组,您首先需要匹配AAAB

这可能有效:

type A0<'b, 'c> =
| AA of AA<'b>
| AB of AB<'c>

type A<'a, 'b, 'c> = A0<'b, 'c> * 'a

let f (a1:A<_,_,_>) =
    snd a1

您使用Tmp<_>解决方案等同于使用元组。

BTW在F#中元素的顺序很重要,为了访问类型AA,需要在类型A之前声明它。您的第一个示例应如下所示:

type AA<'a, 'b> = {
  Code : 'a
  Time : 'b }

type AB<'a, 'c> = {
  Code : 'a
  Whatsoever : 'c }

type A<'a, 'b, 'c> =
| AA of AA<'a, 'b>
| AB of AB<'a, 'c>

let f (a1:A<_,_,_>) =
    match a1 with
    | AA a -> a.Code

还要使用通用参数,例如'a'b,它们需要在顶部声明:

type A<'a, 'b, 'c> = ...

答案 1 :(得分:0)

我可能有一个想法,使用通用类型,例如:

type A =
| AA of Tmp<AA>
| AB of Tmp<AB>

type Tmp<'T> =
{ Code : 'a
  Other : 'T }

type AA = 
{ Time : 'b }

type AB =
{ Whatsoever : 'c }