F#函数参数类型的注释不工作

问题描述:

我想有一个F#函数参数的特定类型:F#函数参数类型的注释不工作

type NewType = string*int 

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

testFunction ("test", 3) 

我希望函数的类型是:

NewType -> NewType 

但功能类型是:

string*int -> NewType 

我该怎么办才能强制arg1参数的类型为“NewType”?

type NewType = string * int是所谓的类型缩写。它给出了另一种类型的名称或别名,但在编译过程中被擦除。没有封装,没有新的参考,基本上没有新的类型。

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

如果你想达到的只是更好的可读性,这可能不成问题。如果我在代码中看到let testFunction (arg1:NewType) : NewType = ...,尤其是在GitHub上没有智能感知工具提示的网络中,即使“实际”类型实际上是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/

+1

但为什么返回类型是“NewType”,为什么它使用返回类型而不是参数。顺便谢谢你的链接! – FraK

+1

@FraK,这是一个很好的问题,而我不知道比其他一个满意的答案:这是编译器的当前版本如何决定这样做(来源例如:https://github.com/fsharp/fsharp /问题/ 717)。正如Tomas所说的那样,原始类型和别名对于编译器(和其他工具)是可以互换的,并且它不能保证你什么时候会看到其中一个。 –

+0

感谢您的回答 – FraK

NewType的类型声明是一个类型别名,这意味着NewType是可交换与string * int - 编译器把他们当作一回事,有时这意味着它将尽管有类型注释报告一个取代另一个。

如果你想要一个总是需要通过其全名引用的类型,你需要将它定义为一个明确的新类型 - 在这一点上,最好使用一个记录(它也会让你的名字单独的字段),但是如果你想要的东西简洁,你可以使用一个单一的情况下,判别联合代替:

type NewType = NT of (string*int) 

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

testFunction (NT("test", 3)) 
+0

但为什么返回类型总是工作,它是“NewType”而不是字符串* int? – FraK

+0

@FraK我认为它仅仅是在编译器中的一些实现细节的副作用 - 统一两类't1'和't2'时,编译器检查,如果他们是平等的 - 然后挑选并使用其中的一个作为键入它显示的名称。 –

+0

感谢您的回答 – FraK