Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does F# constrain my code and remove generics?

Tags:

f#

type VBO<'T when 'T : (new : unit -> 'T) and 'T : struct and 'T :> ValueType> = 
    { Handle : int
      target : BufferTarget
      size : int
      dataSize : int
      data : 'T []
      pos : int
      usage : BufferUsageHint }

type VBO = 
    static member Create(target, size, pos, usage, (data : Vector3 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)

    // Type mismatch. Expecting Vector3 but found Vector2
    static member Create(target, size, pos, usage, (data : Vector2 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)

    // This construct causes code to be less generic than indicated by the type annotations.
    // The type variable 'T has been constrained to be type 'Vector3'.
    static member CreateImpl(target, size, pos, usage, dataSize, (data : 'T [])) = 
        let h = GL.GenBuffer()
        { Handle = h
          target = target
          size = size
          dataSize = dataSize
          data = data
          pos = pos
          usage = usage }

F# tries to constrain my code but I want it to be generic. I don't really care about what type the data is I just need it pass in the correct dataSize.

What have I done wrong?

like image 276
Maik Klein Avatar asked Feb 21 '26 05:02

Maik Klein


1 Answers

The F# compiler seems to specialise generic types if they are used at a particular instantiation in the same block of code. Try splitting up your declaration like this:

type VBO<'T when 'T : (new : unit -> 'T) and 'T : struct and 'T :> ValueType> = 
    { Handle : int
      target : BufferTarget
      size : int
      dataSize : int
      data : 'T []
      pos : int
      usage : BufferUsageHint }

type VBO = 
    static member CreateImpl(target, size, pos, usage, dataSize, (data : 'T [])) = 
        let h = GL.GenBuffer()
        { Handle = h
          target = target
          size = size
          dataSize = dataSize
          data = data
          pos = pos
          usage = usage }

type VBO with
    static member Create(target, size, pos, usage, (data : Vector3 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)

    static member Create(target, size, pos, usage, (data : Vector2 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)
like image 191
GS - Apologise to Monica Avatar answered Feb 22 '26 17:02

GS - Apologise to Monica