匹配判别联合类型

3

第一次使用F#进行生产时需要一些帮助。请查看以下代码,在每行添加了我收到的警告作为注释:

type AssetClass = 
    | Corp
    | Corp_SME
    | Res_Mort
    | Qual_Ret
    | Ret_Oth

let Correlation assetClass pd sales = 
    match assetClass with 
    | Corp -> 0.12 
    | CORP_SME -> 0.24 // warning FS0049: Uppercase variable identifiers
    | Res_Mort -> 0.15 // warning FS0026: This rule will never be matched
    | Qual_Ret -> 0.04 // warning FS0026: This rule will never be matched
    | Ret_Oth  -> 0.03 // warning FS0026: This rule will never be matched

我检查了一下,它并没有虚张声势,第三个和其他情况确实被忽略了。这里我还缺少什么?(实际实现中我使用了pd和sales输入,这里我只是省略了公式。)

我想要做的是像在C#中使用枚举一样使用判别联合,并对其进行切换。所以在C#中,我会这样输入:

    enum AssetClass {
        Corp,
        Corp_SME,
        Ret_Oth
    }

    float Correlation(AssetClass assetClass){
        switch(assetClass){
            case Corp: return 0.12; 
            case Corp_SME: return 0.12;
            case Ret_Oth: return 0.12; 
        }
    }

有人能帮我吗?

提前致谢,

Gert-Jan

2个回答

6

你将构造函数命名为Corp_SME,但尝试将其与CORP_SME(全大写)匹配。由于这不是任何构造函数的名称,F#假定它是一个变量名(因此警告大写变量名),然后当然匹配以前未匹配的所有内容(因此随后的警告)。


2
作为附注,你也可以在F#中声明enum类型。要做到这一点,只需将一些整数值添加到类型的各个情况中即可。
type AssetClass = 
    | Corp = 0
    | Corp_SME = 1
    | Res_Mort = 2
    | Qual_Ret = 3 
    | Ret_Oth = 4

要在模式匹配中使用enum,您需要使用完全限定名称,这样就不会出现意外的问题 - 您必须编写| AssetClass.Corp -> ...。如果要对常规的判别联合获取此行为,则可以使用[<RequireQualifiedAccess>]属性注释该类型。这可能是一个好主意,因为您不会污染命名空间(但仅当我有太多DUs或一些冲突的名称时才使用它)。

嗨,Tomas,谢谢!只是想澄清一下,如果我添加整数,它实际上将是一个.Net枚举,那么我可以在C#项目中使用它吗?如果我不添加整数但保持代码不变,我会得到什么?这样做的原因是什么? - gjvdkamp
1
@gjvdkamp 如果您添加整数,则变成可从C#使用的“枚举”。如果您不添加它们,则将是F#判别联合,这在从C#中使用时会更加困难(它具有一些“枚举”的“标记”属性)。 F#使用不同表示的原因是您可以具有带有值的情况(例如| Corp of int)。 - Tomas Petricek
嗨Tomas,谢谢。我用反编译器查看了生成的代码,不指定整数会导致嵌套类的联合体出现很多不同的代码。我将坚持指定int值。再次感谢! - gjvdkamp
@gjvdkamp: 是的,每个判别式联合的情况都会编译成一个继承类(一个情况可能有不同的属性,所以DU被表示为类层次结构)。当您编写纯F#代码时,无需担心这一点,但如果您想从C#中使用它,则最好暴露更好的API(例如使用F#枚举或编写带有成员的F#包装器类)。 - Tomas Petricek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接