Навеяно вялотекущей дискуссией про зависимые типы.
Берём такую задачку. Нужно взять из какого-то внешнего источника (пофиг, что это будет - может быть, например, пользовательский ввод) число, составить два массива соответствующей длины - заполнив их, например, значениями какой-то функции от индекса - после чего посчитать их скалярное произведение.
Нам хочется, чтобы компилятор гарантировал нам, что длины этих векторов одинаковы. Чтобы если мы где-то наглючили и породили вектора разной длины, программа не скомпилировалась бы.
Пример того, как подобные вещи могут делаться в Хаскеле:
module Test where
data Nil = Nil
data Cons a = Cons Integer a
class ScalarProduct a where scalarProduct :: a -> a -> Integer
instance ScalarProduct Nil where scalarProduct Nil Nil = 0
instance ScalarProduct a => ScalarProduct (Cons a) where scalarProduct (Cons n1 a1) (Cons n2 a2) = n1 * n2 + scalarProduct a1 a2
main :: Integer -> Integer
main n = main' n 0 Nil Nil where
main' :: ScalarProduct a => Integer -> Integer -> a -> a -> Integer
main' 0 _ as bs = scalarProduct as bs
main' n i as bs = main' (n-1) (i+1) (Cons (2*i+1) as) (Cons (i^2) bs)
Я попытался воспроизвести то же самое в плюсах, используя шаблоны вместо Cons и main'. Наткнулся на бесконечное разворачивание шаблонов. Товарищи плюсисты, как делаются подобные вещи?