Generic function to double a value

See the following functions. dbl2 works with SIMD inputs, but dbl does not compile: error: expected a type, not a value.
How can I implement this generic dbl without using SIMD types?

fn dbl[T: DType](x: T) -> T:
    return 2*x

fn dbl2[T: DType](x: Scalar[T]) -> Scalar[T]:
    return 2*x

fn main():
    var x = 4
    var y = dbl(x)
    print(y)

    var x2 = SIMD[DType.float32, 1](4)
    var y2 = dbl2(x2)
    print(y2)

Numerical values in Mojo are SIMD based that means DType by its own needs to be wrapped in SIMD. The Scalar[T] is SIMD[T, 1]where 1 is the SIMD width. For convenience there’re SIMD aliases for each DType like Float32 which corresponds to DType.float32.

If we do var x = 4, the type of x is Int. The dbl2(x) does not work in this case. However, if I do var x = Int32(4), dbl2(x) works.
Intbeing used by default and not being one of the Int32, Int16 etc looks strange to me. It can create inconsistencies, and the example here is one such case.

I want to simplify this function a bit more and I was thinking about having something like this:

fn dbl[dT: DType, T: Scalar[dT](x: T) -> T:

My intent is to create a type T based on dT.
T however is seen as a value of type Scalar[dT]and therefore this exact code does not work.

Is there a way to make Ta type?

Correct, should’ve mentioned Int is different and is like usize but can be converted to Int32 or Int64.

I want to simplify this function a bit more and I was thinking about having something like this:

fn dbl[dT: DType, T: Scalar[dT](x: T) -> T:

I think what you what is perhaps something like this? Note that param is compile-time (see alias in main) and arg is runtime value:

fn foo[dtype: DType, param: Scalar[dtype]](arg: Scalar[dtype]) -> Scalar[dtype]:
    return param * arg

fn main():
    alias param = 2
    x= foo[DType.int32, param](Int32(2))
    print(x)