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 )
如果你看一下上面的代码,你会发现,该函数并没有像它应该的那样通用。
首先,在max表达式中使用0会将类型钳制为int。但它应该是Point<'t>
具有的类型,而不是Point<int>
。
但更重要的是,如果将签名类型用于`t。
,则此函数只能按预期工作这提出了我的一些问题:
提前谢谢。
答案 0 :(得分:5)
这使它成为通用的:
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X - p1.X) zero, max (p2.Y - p1.Y) zero )
但是没有办法将它约束为已签名的原始类型。
答案 1 :(得分:5)
已经回答的第一个问题的解决方案是使用内联函数和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
通常,如果要将任何泛型函数限制为有符号类型,可以定义此函数:
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 )
最后关于你的第三个问题,我不太清楚扩展类型系统是什么意思。您可以自己创建静态约束,从这个意义上说,系统已经是可扩展的。
前段时间我做了一个项目来模拟一些Haskell类型,该项目代码的一部分仍然在FsControl的模块中,你可以知道你可以用这些约束达到什么级别。< / p>