f# 中用户定义类型的混淆

Confusion on user defined types in f#

对于int、string等内置类型,在函数中注解的方式如下:

let testFunction (x:int) = x * x

但是对于用户定义的类型,使用它们的方式是不同的。像下面这个:

type NewType = NewType of int

let test (NewType a)= a * 2

但是如果我用下面的方式表达它,解释器会给我不匹配类型错误(int vs NewType):

let test (a:NewType) = a * 2

为什么会这样?

这是一个类型注释:

let testFunction (x:int) = x * x

但在行中:

let test (NewType a)= a * 2

这不是类型注释。它通过模式匹配称为分解。模式匹配也可以应用于您的示例中的函数参数。它所做的是展开 NewType 中包含的 int 值并将其绑定到 a 值。这就是为什么你可以做乘法,因为它是在 int 值上而不是在 NewType

上完成的

最后一行也是类型注解:

let test (a:NewType) = a * 2

它不起作用,因为默认情况下将乘法推断为 int,并且注释表明 a 类型是 NewType,这就是您收到此错误消息的原因。你必须像你做的那样打开它 let test (a:NewType) = a * 2

您将模式匹配与类型注释混淆了。您的第二个示例使用了正确的类型注释:

let test (a:NewType) = a * 2

不幸的是,这意味着您无法在没有模式匹配的情况下访问类型构造函数的 int 参数以提取它,如下所示:

let test (a:NewType) =
    match a with
    | NewType x -> x * 2

第一个对您有用的情况不是使用类型注释,而是将模式匹配作为参数的一部分,因此您尝试访问的值 已经给了一个名字,不需要进一步的模式匹配。如果您的类型有不止一种可能的模式,

type NewType = NewType of int
             | OtherType of float

并且您尝试使用模式而不是类型注释以第一种方式编写代码,您会看到一条警告,指出您的模式匹配不完整:

> let testcode (NewType a) = a * 2;;                  

  let testcode (NewType a) = a * 2;;
  --------------^^^^^^^^^

warning FS0025: Incomplete pattern matches on this expression. For example, 
the value 'OtherType (_)' may indicate a case not covered by the pattern(s).