Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

single and double cannot be augmented with a Measure

Does anyone know why the [< Measure>] type only augment some algebraic types? That so many useful types cannot be augmented with a Measure looks strange to me.

type FooType =
| FooByte       of byte<1>          // Error
| FooSbyte      of sbyte<1>         // Ok
| FooInt16      of int16<1>         // Ok
| FooUint16     of uint16<1>        // Error
| FooInt        of int<1>           // Ok
| FooInt32      of uint32<1>        // Error
| FooInt64      of int64<1>         // Ok
| FooUint64     of uint64<1>        // Error
| FooNativeint  of nativeint<1>     // Error
| FooUnativeint of unativeint<1>    // Error
| FooChar       of char<1>          // Error
| FooDecimal    of decimal<1>       // Ok
| FooFloat32    of float32<1>       // Ok
| FooSingle     of single<1>        // Error
| FooFLoat      of float<1>         // Ok
| FooDouble     of double<1>        // Error
like image 760
ebaklund Avatar asked Jan 14 '23 14:01

ebaklund


2 Answers

Well, there are two different issues here:

  1. It appears that the unsigned types can't be annotated by design. I'm not sure why this is, but you can get a pretty informative error message to this effect if you try something like let _ = 1u<1>.
  2. Because of how type synonyms work, you can only use measures with "real" types and not with their synonyms. This is why you can use measures with float32 and float, but not single and double. Note that the same would be true of int32, too.
like image 134
kvb Avatar answered Jan 21 '23 23:01

kvb


According to the spec, only the following literal types can have measures

  sbyte < measure-literal > //signed byte
  int16 < measure-literal >
  int32 < measure-literal >
  int64 < measure-literal >
  ieee32 < measure-literal > //float32
  ieee64 < measure-literal > //float
  decimal < measure-literal >

So this is why the unsigned types do not have measure types. Also, form a physical perspective, almost any quantity with units can be negative, so this seems like a reasonable alternative.

The reason why the rest don't work is from the spec:

The F# core library defines the following types:

type float<[<Measure>] 'U>
type float32<[<Measure>] 'U>
type decimal<[<Measure>] 'U>
type int<[<Measure>] 'U>
type sbyte<[<Measure>] 'U>
type int16<[<Measure>] 'U>
type int64<[<Measure>] 'U>

which is why you can't do single<1> as there is no relevant type.

like image 41
John Palmer Avatar answered Jan 21 '23 22:01

John Palmer