Bit*_*ler 2 f# inline type-constraints
type Point<'t> =
val X : 't
val Y : 't
new(x : 't,y : 't) = { X = x; Y = y }
let clampedSubtract (p1:Point<_>) (p2:Point<_>) =
Point( max (p2.X - p1.X) 0, max (p2.Y - p1.Y) 0 )
Run Code Online (Sandbox Code Playgroud)
如果你看一下上面的代码,你会注意到,该函数并没有像它应该的那样实现.
首先,使用max表达式中的0将类型钳制为int.但它应该是任何类型的类型Point<'t>,而不是Point<int>.
但更重要的是,如果将签名类型用于`t,则此函数只能按预期工作.
这提出了我的一些问题:
提前致谢.
这使它成为通用的:
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X - p1.X) zero, max (p2.Y - p1.Y) zero )
Run Code Online (Sandbox Code Playgroud)
但是没有办法将它限制为有符号的原始类型.
已经回答的第一个问题的解决方案是使用内联函数和GenericZero,这就是全部.
关于签名限制,实际上有一种简单的方法将其限制为签名类型.在某处使用仅为签名类型定义的泛型一元否定:
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X + -p1.X) zero, max (p2.Y + -p1.Y) zero )
let result1 = clampedSubtract (Point(4 , 5 )) (Point(4 , 5 ))
let result2 = clampedSubtract (Point(4y , 5y )) (Point(4y , 5y ))
let result3 = clampedSubtract (Point(4uy, 5uy)) (Point(4uy, 5uy)) // doesn't compile
Run Code Online (Sandbox Code Playgroud)
通常,如果要将任何泛型函数限制为有符号类型,可以定义此函数:
let inline whenSigned x = ignore (-x)
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
whenSigned p1.X
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X - p1.X) zero, max (p2.Y - p1.Y) zero )
Run Code Online (Sandbox Code Playgroud)
最后关于你的第三个问题,我不清楚扩展类型系统是什么意思.您可以自己创建静态约束,从这个意义上说,系统已经是可扩展的.
前段时间我做了一个项目来模拟一些Haskell类型,该项目代码的一部分仍然在FsControl中的模块中,你可以知道你可以使用这些约束的级别.