LINUX.ORG.RU

Равные длины векторов


0

0

Навеяно вялотекущей дискуссией про зависимые типы.

Берём такую задачку. Нужно взять из какого-то внешнего источника (пофиг, что это будет - может быть, например, пользовательский ввод) число, составить два массива соответствующей длины - заполнив их, например, значениями какой-то функции от индекса - после чего посчитать их скалярное произведение.

Нам хочется, чтобы компилятор гарантировал нам, что длины этих векторов одинаковы. Чтобы если мы где-то наглючили и породили вектора разной длины, программа не скомпилировалась бы.

Пример того, как подобные вещи могут делаться в Хаскеле:

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'. Наткнулся на бесконечное разворачивание шаблонов. Товарищи плюсисты, как делаются подобные вещи?

★★★★★

Ответ на: комментарий от tailgunner

> Это тема холивора, но я недостаточно хорошо понимаю, что делает unsafePerformIO, чтобы участвовать в таком холиворе

unsafePerformIO, как и unsafeCoerce - дырка в системе типов. От которой, на самом деле, легко закрыться: не импортировать модуль System.IO.Unsafe. Если ваш сосед его импортировал - набейте ему морду. Вы увидите это сразу, в первых строчках модуля, над которым работаете.

Если бы это было не так, lambdabot работать не смог бы. Точнее, смог бы, но его ломали бы раз в минуту.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

> И что?

Вы спросили, как компилятор что-то может гарантировать в рантайме. Я ответил.

В С++ такое вполне реально.

Нет. В C++ такое невозможно.

Но повторяю, если значение не известно на этапе компиляции, то компилятор его проверить не может.

Никто не говорит «проверить», речь идёт о «гарантировать». Я не могу проверить размер всех ворон на свете, но я готов держать с вами пари на любую сумму, что вороны ростом 10 метров в настоящее время в мире не существует.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

И ещё:

Если у Хаскеля развита рантаймовая поддержка, то это не доказывает, что он способен проверить на стадии копиляции.

Хаскель не делает рантаймовых проверок, о которых вы его явно не просите.

Просто я знаю больше вас.

Это ваше субъективное мнение.

Аргументированное. Если вы до сих пор считаете, что статическая типизация означает объявление переменных - я стопроцентно знаю больше вас.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

> Вы очень жирный троль. Дискутировать с Вами больше смысла не вижу, гарантируйте что угодно.

Cлив засчитан. Ни одного аргумента с вашей стороны высказано не было, вы смогли только тявкнуть и сбежать.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster
var i
if (userWantsToUseString()) {
  i = "hello";
} else {
  i = 1;
}
f(i);

динамическая типизация, компилятор не знает тип переменной i.

i = 5

компилятор знает, что i - целочисленного типа. типизация статическая.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> динамическая типизация, компилятор не знает тип переменной i.

На каком языке вы пишете, начнём с этого?

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

А, вы ещё здесь?

Тогда попробуйте хоть как-то аргументировать вашу точку зрения.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от jtootf

>> я недостаточно хорошо понимаю, что делает unsafePerformIO, чтобы участвовать в таком холиворе :)

http://www.xkcd.ru/292/

Хм,ты хочешь сказать, что и компилятор Хаскеля не дает никаких гарантий? Я не верю!!!111

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Хм,ты хочешь сказать, что и компилятор Хаскеля не дает никаких гарантий? Я не верю!

Если использовать FFI (а unsafePerformIO тоже относится к FFI, по крайней мере формально), то никаких, да. Но такие вещи очень легко отслеживаются.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Legioner

> А что?

А то, что статическая у вас типизация или динамическая - зависит не от внешнего вида кода, а от языка.

Вот, например, вполне статически типизированный хаскель: [code] i = if userWantsToUseString then «Hello» else 5 [/code] Я могу заставить это компилиться. Правда, тогда i будет типа String, в любом случае.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Miguel

Тьху.

i = if userWantsToUseString then "Hello" else 5

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Miguel

> [code] i = if userWantsToUseString then «Hello» else 5 [/code]

Я могу заставить это компилиться.

И что значит эта странная конструкция?

tailgunner ★★★★★
()

Ваша навороченная программа аналог следующей?

#include <iostream>
using namespace std;

int main() {
	int n, s=0;
	cin >> n;
	for (int i=0; i<n; ++i)
		s+=(2*i+1)*(i*i);
	cout << s << endl;
	return 0;
}
[/cpp]
anonymous
()
Ответ на: комментарий от tailgunner

> И что значит эта странная конструкция?

Ну, мне сначала придётся определить instance Num Char. Фишка в том, что в Хаскеле числовые литералы - полиморфные. Так что 5 имеет тип не Integer, а Num a => a. Если строки тоже станут инстансами класса Num, то вся конструкция будет законной.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> Ваша навороченная программа аналог следующей?

Что вы понимаете под словом «аналог»?

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

> Кстати, у хаскеля есть компилятор?

GHC, nhc98, YHC, HBC, UHC, Jhc, LHC

А то только интерпертаторы попадались.

Интересно, кем надо быть, чтобы из как минимум семи компиляторов, один из которых является основной реализацией (GHC), и двух интерпретаторов (Hugs и HBI) найти только интерпретаторы?

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

> Вы продолжаете переходы на личности?

Ещё и не начинал.

Мне хаскель не интересен.

Тогда зачем вам его компилятор?

Miguel ★★★★★
() автор топика

у меня тоже началось прикольное бесконечное разворачивание шаблонов, а без него код становится чересчур длинным. сижу думаю как покороче...

www_linux_org_ru ★★★★★
()

> число, составить два массива соответствующей длины - заполнив их

Если число одно, то все массивы будут гарантированно одинаковой длины, не?

Вам не пора выспаться?

ip1981 ☆☆
()
Ответ на: комментарий от ip1981

> Вам не пора выспаться?

Ещё один. Когда ж вы все передохнете...

А если я обшибся? Если мои массивы изначально содержали какие-то числа и я по ошибке сделал их разной длины? Имеет человек, даже если он программист на АЭС, право на ошибку?

Система типов на то и существует, чтобы ловить за руку в подобных случаях.

Miguel ★★★★★
() автор топика

В рантайме никаких типов нет, это понятие этапа компиляции(по крайней мере в компилируемых языках, таких как С++). Вначале я вам задал вполне конкретные вопросы, а вы мне ахинею про типизацию. Хотя вряд ли от Вас дождёшся конструктива.

Booster ★★
()
Ответ на: комментарий от Waterlaz

Я сказал, что компиляция рантайм не контролирует, а мне про типы. Ещё я написал, что данная задача сводится к следущей: есть две переменных инициализируемых пользователем в рантайме, нужно на этапе компиляции определить равны ли они. Или задача не полна или бред. Что хочет гарантировать ТС, я так и не понял. Кто троль?

Booster ★★
()
Ответ на: комментарий от Booster

> В рантайме никаких типов нет, это понятие этапа компиляции(по крайней мере в компилируемых языках, таких как С++).

Во-1, вы ничего не знаете про компилируемые языки. Очень многие сохраняют типы, по крайней мере, частично.

Во-2, даже если типы не сохраняются (а GHC, вроде бы, не сохраняет), ОШИБКИ типизации остаются всё равно. Когда в РАНТАЙМЕ вместо числа пришла строка - это ошибка типизации, даже если у вас C++. Языки с СИЛЬНОЙ типизацией исключают подобные ошибки. То бишь - ГАРАНТИРУЮТ их отсутствие.

Вначале я вам задал вполне конкретные вопросы

На каждый ваш вопрос, сколь бы неграмотно он ни был сформулирован, был дан ответ.

Miguel ★★★★★
() автор топика

Ещё я не понял зачем меня хотели подловить на не знании статической и динамической типизации и что я идиот. Только какое это отношение имеет к сабжу?

Booster ★★
()
Ответ на: комментарий от Booster

> Я сказал, что компиляция рантайм не контролирует

Подобную фразу - которую вы раньше не произносили - можно понять слишком многими способами. Вплоть до следующего: написанная программа не имеет никакого отношения к тому, что будет делать компьютер. Вы сами понимаете, что это чушь?

Ещё я написал, что данная задача сводится к следущей: есть две переменных инициализируемых пользователем в рантайме, нужно на этапе компиляции определить равны ли они.

А вам популярно ответили, что подобной задачи никто в этом треде (кроме вас) не ставил.

Что хочет гарантировать ТС, я так и не понял.

В данном случае - совпадение длин двух массивов. Чтобы программа, допускающая, что массивы могут оказаться разной длины, не скомпилировалась. Я показал, как это делается, а мой оппонент www_linux_org_ru показал строчку, нарушающую этот инвариант, и убедился, что она не компилируется.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Booster

Сам я по всей видимости не в состоянии.

сочувствую

jtootf ★★★★★
()
Ответ на: комментарий от Booster

> Ещё я не понял зачем меня хотели подловить на не знании статической и динамической типизации

Вы сформулировали своё понимание разницы между статической и динамической типизацией. Вам было объяснено, что ваше понимание не имеет отношения к действительности.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Miguel

Можно до посинения спорить есть в рантайме типы или нет. Проверка типов существует только на этапе компиляции и точка. Но я снова спрашиваю какое это имеет отношение к теме? Или Вы хотите проверку типов использовать на стадии выполнения? Должен Вас разочаровать.

Booster ★★
()
Ответ на: комментарий от Booster

Ахинея это вот это:

В рантайме никаких типов нет, это понятие этапа компиляции(по крайней мере в компилируемых языках, таких как С++)

Love5an
()
Ответ на: комментарий от Booster

> Проверка типов существует только на этапе компиляции и точка.

В статически типизированных языках. А ошибки типизации могут существовать в рантайме.

Но я снова спрашиваю какое это имеет отношение к теме?

Вы спросили, как компилятор может гарантировать что-то в рантайме. Я вам ответил: при помощи статической типизации. Статическая типизация и есть способ гарантировать корректное поведение значений в рантайме.

Miguel ★★★★★
() автор топика
Ответ на: комментарий от Miguel

>В данном случае - совпадение длин двух массивов. Чтобы программа, допускающая, что массивы могут оказаться разной длины, не скомпилировалась. Я показал, как это делается, а мой оппонент www_linux_org_ru показал строчку, нарушающую этот инвариант, и убедился, что она не компилируется.
Задавайте длину массива константно, тогда компилятор будет знать его размер и можно будет проверить.

А вам популярно ответили, что подобной задачи никто в этом треде (кроме вас) не ставил.

Конечно, но если решите её, то решите и свою.

Booster ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.