F# 函数参数类型注释不起作用

F# function arguments type annotation not working

我想为 F# 函数中的参数设置特定类型:

type NewType = string*int

let testFunction (arg1:NewType) : NewType =
  ("resultString", 2)

testFunction ("test", 3)

我希望函数的类型是:

NewType -> NewType

但是函数类型是:

string*int -> NewType

我应该怎么做才能将参数 arg1 的类型强制为 "NewType"?

NewType 的类型声明是一个类型别名,这意味着 NewType 可以与 string * int 交换——编译器将它们视为同一事物,有时这意味着它将尽管有类型注释,但报告一个代替另一个。

如果您想要一个始终必须通过其全名引用的类型,您需要将其定义为一个显式的新类型 - 此时,最好使用记录(这也将让你命名各个字段),但如果你想要简洁的东西,你可以改用单案例区分联合:

type NewType = NT of (string*int)

let testFunction (NT arg1) : NewType =
  NT("resultString", 2)

testFunction (NT("test", 3))

type NewType = string * int 就是所谓的类型缩写。它为另一种类型提供名称或别名,但在编译期间会被删除。没有封装,没有新的引用,基本上也没有新的类型。

它可以用作文档,但 F# 的编译器将新名称和别名类型视为相同。如果您使用 public function/method 创建一个 DLL,并且使用 NewType 并尝试从另一个项目调用它,这一点尤其明显 - 您会看到混合结果,就像您的情况一样。

如果您想要实现的只是更好的可读性,这可能不是问题。如果我在代码中看到 let testFunction (arg1:NewType) : NewType = ...,尤其是在没有 IntelliSense 工具提示的网络上,例如 GitHub,这仍然让我很好地了解函数需要什么和 returns,甚至如果 "real" 类型在实践中是 string * int.

如果你想要更好的类型安全,通常的做法是定义一个单例区分联合,你可以像这样结合模式匹配:

type NewType = NewType of (string * int)

let testFunction (NewType arg1): NewType =
    NewType ("resultString", 2)

testFunction (NewType ("test", 3))

您可以在此处和该系列的其他文章中阅读更多内容:https://fsharpforfunandprofit.com/posts/type-abbreviations/