F# 为什么在文件之间移动代码时类型会改变
我有两个文件。第一个文件名为RailwayCombinator.fs,其内容如下:F# 为什么在文件之间移动代码时类型会改变,f#,inline,F#,Inline,我有两个文件。第一个文件名为RailwayCombinator.fs,其内容如下: module RailwayCombinator let (|Uncarbonated|Carbonated|) = function | Choice1Of2 s -> Uncarbonated s | Choice2Of2 f -> Carbonated f let uncarbonated x = Choice1Of2
module RailwayCombinator
let (|Uncarbonated|Carbonated|) =
function
| Choice1Of2 s -> Uncarbonated s
| Choice2Of2 f -> Carbonated f
let uncarbonated x = Choice1Of2 x
let carbonated x = Choice2Of2 x
let either successFunc failureFunc twoTrackInput =
match twoTrackInput with
| Uncarbonated s -> successFunc s
| Carbonated f -> failureFunc f
第二个文件名为Program.fs,其内容如下:
open RailwayCombinator
let carbonate factor label i =
if i % factor = 0 then
carbonated label
else
uncarbonated i
let fizzBuzz =
let carbonateAll =
carbonate 3 "Fizz" <+> carbonate 5 "Buzz"
carbonateAll
我还注意到,的签名根据它所在的文件而改变,但我不知道为什么签名会改变。在RailwayCombinator中的签名为:
val ( <+> ) :
switch1:('a -> Choice<'b,int>) ->
switch2:('a -> Choice<'c,int>) -> x:'a -> Choice<'b,int>
val():
开关1:('a->Choice您的
组合器的实现使用+
运算符。F#编译器不知道如何使此为泛型(.NET泛型没有泛型约束,表示类型应为“带有+运算符的任何内容”)因此,F#编译器根据使用运算符的定义下面的第一段代码选择
的第一种类型
您可以通过内联定义来解决此问题:
let inline (<+>) switch1 switch2 x =
match (switch1 x),(switch2 x) with
| Carbonated s1,Carbonated s2 -> carbonated (s1 + s2)
| Uncarbonated f1,Carbonated s2 -> carbonated s2
| Carbonated s1,Uncarbonated f2 -> carbonated s1
| Uncarbonated f1,Uncarbonated f2 -> uncarbonated f1
let inline()开关1开关2 x=
将(开关1 x)、(开关2 x)与
|碳化s1,碳化s2->碳化(s1+s2)
|未碳化f1,碳化s2->碳化s2
|碳化s1,未碳化f2->碳化s1
|未碳化f1,未碳化f2->未碳化f1
内联
由F#编译器直接处理,因此它们支持更强大的泛型约束—包括一个表示“任何带+”的约束。您的
组合器的实现使用了+
操作符。F#编译器不知道如何使这个泛型(.NET泛型没有泛型约束,即类型应为“带有+运算符的任何内容”)。因此,F#编译器根据使用运算符的定义下面的第一段代码选择
的第一个类型
您可以通过内联定义来解决此问题:
let inline (<+>) switch1 switch2 x =
match (switch1 x),(switch2 x) with
| Carbonated s1,Carbonated s2 -> carbonated (s1 + s2)
| Uncarbonated f1,Carbonated s2 -> carbonated s2
| Carbonated s1,Uncarbonated f2 -> carbonated s1
| Uncarbonated f1,Uncarbonated f2 -> uncarbonated f1
let inline()开关1开关2 x=
将(开关1 x)、(开关2 x)与
|碳化s1,碳化s2->碳化(s1+s2)
|未碳化f1,碳化s2->碳化s2
|碳化s1,未碳化f2->碳化s1
|未碳化f1,未碳化f2->未碳化f1
inline
由F#编译器直接处理,因此它们支持更强大的通用约束,包括一个表示“任何带+”的约束.猜测时,将函数标记为内联将解决此问题,因为+的默认值为int,但在第二种情况下,您使用字符串强制更改。猜测时,将函数标记为内联将解决此问题,因为+的默认值为int,但在第二种情况下,您使用字符串强制更改。
val ( <+> ) :
switch1:('a -> Choice<'b,int>) ->
switch2:('a -> Choice<'c,int>) -> x:'a -> Choice<'b,int>
val ( <+> ) :
switch1:('a -> Choice<'b,string>) ->
switch2:('a -> Choice<'c,string>) -> x:'a -> Choice<'b,string>
let inline (<+>) switch1 switch2 x =
match (switch1 x),(switch2 x) with
| Carbonated s1,Carbonated s2 -> carbonated (s1 + s2)
| Uncarbonated f1,Carbonated s2 -> carbonated s2
| Carbonated s1,Uncarbonated f2 -> carbonated s1
| Uncarbonated f1,Uncarbonated f2 -> uncarbonated f1