class Matrix(N, M)
def initialize
end
def *(other : Matrix(M, P)) : Matrix(N, P)
Matrix(N, P).new
end
end
m = Matrix(2, 2).new
m * m
undefined constant P
I'd expect compiler to figure out that both P's are supposed to be of the same value
try adding forall M, P at the end of the method definition:
def *(other : Matrix(M, P)) : Matrix(N, P) forall M, P
Same error 馃
It actually works with forall if you omit the return type. That's maybe a bug, not sure.
Yeah, it looks that way. And it should only be forall P because M is already a generic argument.
And you're using 2 as type, you should use a type for N, M and P.
class Matrix(N, M)
def initialize
end
def *(other : Matrix(M, P)) : Matrix(N, P) forall M, N, P
Matrix(N, P).new
end
end
m = Matrix(Int32, Int32).new
m * m
If you omit the return type it works without forall as well.
However, I suspect you are not using generics properly (though I don't know your use case).
class Matrix(T)
def initialize(@n : Int32, @m : Int32)
end
def *(other : Matrix(T))
Matrix(T).new(@n, @m)
end
end
m = Matrix(Int32).new(2, 2)
m * m
@hugoabonizio M and N are not free variables, they're already specified in the generic type arguments and should properly resolve. Only P should be declared explicitly.
I suppose this is just another edge case where the specific implementation for generic type arg as integer is incomplete.
Using integers as generic type arguments to define the dimensions of a matrix is completely legitimate. That's what they're made for.
@hugoabonizio These are just compile-time variables. The main reason I'm using them is to prevent invalid operations at runtime.
A bug in error messages, this should error that the type variable P could not be inferred:
def foo(in : Array(A)) : Array(P) forall A, P
in
end
foo(Array(Int32).new)
A bug in numerical generics, this should infer P:
class Foo(A)
end
def foo(in : Foo(P)) : Foo(P) forall P
in
end
# works
# foo(Foo(Int32).new)
# broken
foo(Foo(1).new)
Using integers as generic type arguments to define the dimensions of a matrix is completely legitimate.
Really nice to know! We learn something new everyday :smile:
class Foo(A)
def sum
A + A
end
end
puts Foo(1).new.sum