, 대답은 :
let inline isValidUnitValue myUnit = myUnit > LanguagePrimitives.GenericZero
그래서 당신이 차별 연합 (EU)을 정의 할 필요가 없습니다.
원래 질문에 대해서는 데이터 유형과 측정 단위에 대해 일반적인 함수를 정의 할 수 있는지 여부는 dropUnit
과 같이 짧습니다. 그러한 함수가 존재한다면 그것은 'a<'b> -> 'a
과 같은 서명을 가지며 그것을 나타 내기 위해 타입 시스템은 더 높은 종류를 구현해야한다.
그러나 과부하 및 인라인 사용하는 트릭이있다 : 오버로드를 사용
1) (라 C#을)
type UnitDropper =
static member drop (x:sbyte<_> ) = sbyte x
static member drop (x:int16<_> ) = int16 x
static member drop (x:int<_> ) = int x
static member drop (x:int64<_> ) = int64 x
static member drop (x:decimal<_>) = decimal x
static member drop (x:float32<_>) = float32 x
static member drop (x:float<_> ) = float x
[<Measure>] type m
let x = UnitDropper.drop 2<m> + 3
을하지만이 정말 일반적인 함수가 아닙니다, 당신은 제네릭 뭔가를 쓸 수 없습니다 그것의 꼭대기. 인라인을 사용
> let inline dropUnitAndAdd3 x = UnitDropper.drop x + 3 ;;
-> error FS0041: A unique overload for method 'drop' could not be determined ...
2), 공통의 비결은 다시 입력한다 :
는
let inline retype (x:'a) : 'b = (# "" x : 'b #)
[<Measure>] type m
let x = retype 2<m> + 3
let inline dropUnitAndAdd3 x = retype x + 3
문제는 retype
이 너무 일반적이기 때문이다, 당신이 쓸 수 있습니다 :
let y = retype 2.0<m> + 3
을
런타임에는 컴파일되지만 실패합니다.과부하 및 인라인 모두 사용
3) :이 트릭은 중간 형식을 통해 오버로드를 사용하여 두 문제를 해결할를, 당신이 얻을 모두 검사 시간 컴파일하고 일반적인 함수를 정의 할 수 있습니다이 방법 : 당신이 컴파일 타임 오류가 발생합니다 마지막 줄에서
type DropUnit = DropUnit with
static member ($) (DropUnit, x:sbyte<_> ) = sbyte x
static member ($) (DropUnit, x:int16<_> ) = int16 x
static member ($) (DropUnit, x:int<_> ) = int x
static member ($) (DropUnit, x:int64<_> ) = int64 x
static member ($) (DropUnit, x:decimal<_>) = decimal x
static member ($) (DropUnit, x:float32<_>) = float32 x
static member ($) (DropUnit, x:float<_> ) = float x
let inline dropUnit x = DropUnit $ x
[<Measure>] type m
let x = dropUnit 2<m> + 3
let inline dropUnitAndAdd3 x = dropUnit x + 3
let y = dropUnit 2.0<m> + 3 //fails at compile-time
: FS0001: The type 'int' does not match the type 'float'
이 방법의 또 다른 장점은 당신이 나를 정적을 정의하여 새로운 유형 나중에 확장 할 수 있다는 것입니다 다음과 같이 유형 정의에서 mber ($)를 입력하십시오.
type MyNumericType<[<Measure 'U>]> =
...
static member dropUoM (x:MyNumericType<_>) : MyNumericType = ...
static member ($) (DropUnit, x:MyNumericType<_>) = MyNumericType.dropUoM(x)
다른 옵션은 인라인 함수를 사용하여 인터페이스를 위장하는 것입니다. –