是否有任何语言将整数数学纳入其类型系统?
Are there any languages which incorporate integer maths into their type system?
我一直在考虑一个假设的语言功能,我想知道是否有任何语言做了类似的事情,我可以从中学习,或者可以提供相关的搜索词。
语言允许使用受限类型参数专门化类型是很常见的,通常称为泛型。例如,Foo<Bar>
作为类型。
我很好奇是否有任何语言允许我们使用特定整数值对类型进行参数化,例如 Foo<10>
。用例的一个简单示例可能是一个固定长度的数组,它可以由类型检查器静态检查。
我对可能允许在类型系统中进行基本数学运算的语言特别感兴趣。此 C# 风格的伪代码会将两个固定长度数组连接成第三个已知长度的固定长度数组,编译器将计算该数组并将其视为常量。
FixedArray<Length1 + Length2> Concat<Length1, Length2>(FixedArray<Length1> a, FixedArray<Length2> b)
where Length1: Integer, >= 0
where Length2: Integer, >= 0
{}
我知道 TypeScript,它很接近。它允许常量作为类型,因此 Foo<10>
是有效的。但是,我相信类型系统将它们更像是枚举或符号,而不是将它们理解为数学值。有一些方法可以使用重载来伪造它。
研究关键字和讨论此类功能的文档 - 即使不是用语言实现 - 也很有趣。不假定对类型理论有深入了解的资源是首选,尽管我会接受任何东西。
在 C++ 中,您可以使用整数参数化模板。实际上标准中有一个template struct array<class T, size_t N>
。您可以定义一个函数以将其与编译时类型检查连接起来,如下所示:
template<class T, size_t N1, size_t N2> array<T, N1+N2> concat(
const array<T, N1> &a, const array<T, N2> &b)
{
array<T, N1+N2> ret;
/* copy data into ret */
return ret;
}
使用时,编译时会检查类型:
array<T, 10> a;
array<T, 5> b;
array<T, 14> ab1 = concat(a, b); // error
array<T, 15> ab2 = concat(a, b); // works
auto ab3 = concat(a, b); // type of ab3 is auto-deduced to array<T, 15>
这是一个working example。
我认为您可能要查找的术语是 dependently typed。这不是一个非常具体的术语,但它意味着类型可以取决于值,通常包括数字。
下面是 Idris 的示例,一种依赖类型的编程语言:
total
append : Vect n a -> Vect m a -> Vect (n + m) a
append Nil ys = ys
append (x :: xs) ys = x :: append xs ys
n
和m
是Vect
的类型参数,表示向量的长度,所以两个Vect
相加的结果长度为n + m
.
我一直在考虑一个假设的语言功能,我想知道是否有任何语言做了类似的事情,我可以从中学习,或者可以提供相关的搜索词。
语言允许使用受限类型参数专门化类型是很常见的,通常称为泛型。例如,Foo<Bar>
作为类型。
我很好奇是否有任何语言允许我们使用特定整数值对类型进行参数化,例如 Foo<10>
。用例的一个简单示例可能是一个固定长度的数组,它可以由类型检查器静态检查。
我对可能允许在类型系统中进行基本数学运算的语言特别感兴趣。此 C# 风格的伪代码会将两个固定长度数组连接成第三个已知长度的固定长度数组,编译器将计算该数组并将其视为常量。
FixedArray<Length1 + Length2> Concat<Length1, Length2>(FixedArray<Length1> a, FixedArray<Length2> b)
where Length1: Integer, >= 0
where Length2: Integer, >= 0
{}
我知道 TypeScript,它很接近。它允许常量作为类型,因此 Foo<10>
是有效的。但是,我相信类型系统将它们更像是枚举或符号,而不是将它们理解为数学值。有一些方法可以使用重载来伪造它。
研究关键字和讨论此类功能的文档 - 即使不是用语言实现 - 也很有趣。不假定对类型理论有深入了解的资源是首选,尽管我会接受任何东西。
在 C++ 中,您可以使用整数参数化模板。实际上标准中有一个template struct array<class T, size_t N>
。您可以定义一个函数以将其与编译时类型检查连接起来,如下所示:
template<class T, size_t N1, size_t N2> array<T, N1+N2> concat(
const array<T, N1> &a, const array<T, N2> &b)
{
array<T, N1+N2> ret;
/* copy data into ret */
return ret;
}
使用时,编译时会检查类型:
array<T, 10> a;
array<T, 5> b;
array<T, 14> ab1 = concat(a, b); // error
array<T, 15> ab2 = concat(a, b); // works
auto ab3 = concat(a, b); // type of ab3 is auto-deduced to array<T, 15>
这是一个working example。
我认为您可能要查找的术语是 dependently typed。这不是一个非常具体的术语,但它意味着类型可以取决于值,通常包括数字。
下面是 Idris 的示例,一种依赖类型的编程语言:
total
append : Vect n a -> Vect m a -> Vect (n + m) a
append Nil ys = ys
append (x :: xs) ys = x :: append xs ys
n
和m
是Vect
的类型参数,表示向量的长度,所以两个Vect
相加的结果长度为n + m
.