Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, VoidEx, Вы писали:
VE>>>>Классы типов — это АлгТД. S>>>Можно развернуть мысль?
VE>>Можно.
V>А можно, для не имеющих достаточной практики в Хаскеле его Prelude пояснить, где здесь используются классы типов?
Можно.
module Equal (
) where
import Prelude hiding (Eq(..))
-- class Eq a where
-- (==) :: a -> a -> Bool
-- (/=) :: a -> a -> Booldata Eq a = EqCtor {
equal :: a -> a -> Bool,
notEqual :: a -> a -> Bool }
-- instance Eq Bool where
-- (==) = eq
-- (/=) = neq
boolEq :: Eq Bool
boolEq = EqCtor eq neq where
eq True True = True
eq False False = True
eq _ _ = False
neq x y = not $ eq x y
-- instance Eq Int where
-- (==) = eq
-- (/=) = neq
intEq :: Eq Int
intEq = EqCtor eq neq where
eq 0 0 = True
eq 0 x = False
eq x 0 = False
eq x y = eq (pred x) (pred y)
neq x y = not $ eq x y
-- foo :: Eq a => a -> a -> a -> Bool
foo :: Eq a -> a -> a -> a -> Bool-- foo x y z = (==) x y || (==) y z
foo (EqCtor eq neq) x y z = eq x y || eq y z
test1 = foo boolEq True False False
test2 = foo intEq 0 2 5
Тип Eq a полностью аналогичен классу Eq.
Отличие в том, что instance может быть только один, и передаётся он неявно.
FR>Рантаймное ветвление при ПМ есть, почему ты и vdimas называете это динамической типизацией я не понимаю,
дай формальное опредение, которое бы строгим образом отличало одно (динамическую типизацию) от другого (runtime-ветвление)?
причем чтобы это определение не зависело от конкретного ЯП, и было одинаково подходящим для произвольного языка.
ззы
так как такого формального определения разницы дать нельзя, то я считаю — что это одно и тоже, а то что некоторые люди пытаются отличать одно от другого является чистой вкусовщиной и субъективизмом
зы
Если один и тот же код над данными выполняет разные операции значит это данные разного типа.
if в генеренном коде, как раз и это обозначает. что код вроде бы один, но данные обрабатывает по разному.
если операция деления выглядит как:
div(a, b)=
if (b == 0)
throw error
else
посчитать сколько раз b входит в a
то этого достаточно для утверждения, что для операции div если два типа: 0 и не 0:
а также достаточно для выделения двух функций:
type number_not_0:number where number != 0;
type 0:number where number == 0;
div(a, number_not_0 b) =
посчитать сколько раз b входит в a
div(_, number_0) =
throw error
Здравствуйте, DarkGray, Вы писали:
VE>>Почему невозможно?
DG>если ты говоришь, что каждая type system полностью независима от другой, и что в типе не указано как он хранится в памяти, то невозможно с map<string, array<int>> работать из haskell-я, из C++ и из питона, обращаешь к представлению данного типа в памяти напрямую.
В типе — не указано. В языке — указано.
VE>>Смотреть на типы с т.з. haskell, C и python — это не выйти в надсистему, а перейти в другую систему и при этом пытаться применить термины из одной системы с другой.
DG>при выходе в надсистему появляется обобщенный Type (будем его писать с большой буквы для однозначности), которые включает в себя C-тип, Haskell-тип, python-тип, ATS-тип и т.д DG>Соответственно Type включает в себя все возможности, которые были у C/Haskell/python/ats-типов и т.д.: DG>если C-тип умеет описывать как данные хранятся в памяти, значит и Type умеет,
C-тип не умеет этого описывать. Как хранятся конкретные типы, описывает язык Си, а не тип. Типизировать программу можно вне зависимости от того, как хранятся данные в памяти. Не надо мешать всё в кучу.
DG>>Это утверждение неявно использует допущение, что описание функции в ЯП и генеренный для нее код соотносится как 1 к 1. DG>>Такое допущение сильно упрощает действительность, и и является неверным и опасным.
FR>Генеренный код в данном случае делает ровно то что описывает ЯП а именно статически типизированную FR>неполиморфную функцию.
FR>Мне кажется ты не понимаешь что в том коде который привел я (и по его мотивам D. Mon) FR>нет разных типов и нет полиморфизма.
с точки зрения какой формальной логики ты утверждаешь, что там этого нет?
с точки зрения конструктивной логики там есть вся необходимая информация для построения разных типов и полиморфизма.
FR>Есть один единственный тип:
FR>type test = Int of int | Float of float | String of string
с точки зрения конструктивной логики (и наличия операций композиции и декомпозиции) — это как минимум 4 типа (вся необходимая информация есть), при необходимости можно построить и другие типы (в частности, type Number = Int of int | Float of float и т.д.)
FR>и фукция dummy_id мономорфна и работает с этим типом а функция dummy2 которую привел FR>D. Mon с массивами этого типа, а не с массивами int, float или string. Так что такая FR>развертка которую ты хочешь просто невозможна.
Здравствуйте, VoidEx, Вы писали:
V>>Это такое условное ветвление, целью которого является выбрать ветку алгоритма, умеющего работать с неким конкретным устройством значения (т.е. с неким конкретным типом).
VE>И if именно это и делает.
Там, где в рамках статически-типизированного языка не выполняется реинтерпретация памяти, то if этого не делает ни разу.
VE>Не путайте то, какие байтики лежат, с типом. В случае указателя конкретное устройство значения одно и то же — указатель, но тип тем не менее разный.
Это ты путаешь. Одинаковое устройство даже двух объявленных одинаково типов не гарантируется в том же С++. А в плане указателей (при чем тут они, кстати?), если работаем именно со значением указателя, а не с указываемой областью памяти, то одинаковое устройство указателей проявляется в полной мере — мы можем присвоить void * значение типизированного указателя, преобразовать в число, получить из числа и т.д. Попробуй преобразовать в число, скажем, struct A {}.
V>>Т.е. имеем следующее: в compile-time пишем алгоритмы под все возможные (или уникально обрабатываемые) типы, ожидаемые в некоей точке алгоритма, а в рантайм через ветвление выбираем одну из веток алгоритма, согласно фактически поданному типу значения.
V>>Для работоспособности этой схемы обязательно нужен некий механизм реинтерпретации памяти. Например, в C# это приведение типов as или через (Type1), в С++ через dynamic_cast или через reinterpret_cast, еще через встроенный рантайм-полиморфизм, в ML-языках через паттерн-матчинг.
VE>Какая связь типов с памятью?
Такая, что в статически-типизированном языке компилятору требуется знать представление любого типа в памяти для генерации кода.
VE>Вот тут, например, о каком механизме реинтерпретации памяти вообще в принципе может идти речь?
А где по ссылке ограничения в реализации, присущие компиляторам статически-типизированных языков? где там вообще идет речь о компиляции vs интерпретации или же где там вообще обсуждается реализация?
В общем, мы уже договорились чуть выше, что статическая типизация и статическая компиляция — вовсе не одно и то же. А ты продолжаешь их путать.
Заметь, в SystemF присутствуют т.н. абстрактные типы данных с конструкторами. А реализация абстрактных типов данных без какой-либо техники динамической диспетчеризации по конкретным устройствам значений, то бишь по конкретным типам, невозможна.
Итого, для статической реализации SystemF нужна вспомогательная система типов, с помощью которой уже можно будет описать абстракции самой SystemF в терминах нижележащей вычислительной модели, например, в плоской памяти, как в Гарвардской или Фон-Неймановской архитектуре.
VE>>>То, что при наличии разных вариантов у АлгТД происходит ветвление — это динамическая типизация в той же мере, что и ветвление по 0 и не 0 в факториале.
V>>Нет.
VE>Да.
VE>Я вас удивлю, но (x:int){x==0} — это тип. У него ровно одно значение. И if это проверяет, а затем работает с этим типом.
Ничем не удивил. Эта такая абстракция Хаскеля на вырожденных АлгТД, потому что натуральные числа или символы в Хаскеле представлены лишь значением дискриминатора. Но если тело "варианта" пустое для всех значений дискриминатора по-определению, то никакой реинтерпретации памяти не требуется, бо все пустые туплы совместимы по представлению... в отличие от случая, когда вместе с дискриминатором хранится некое значение, структура которого неизвестна до момента проверки дискриминатора варианта.
VE>
VE>Formally, a type can be defined as "any property of a programme we can determine without executing the program"
VE>Вы же почему-то под типом подразумеваете какое-то внутреннее представление.
Почему нет, если речь идет непосредственно об этом представлении? Например, когда мы обсуждаем компилятор статически-типизируемого языка, а не некий интерпретатор.
И да, содержимое АлгТД, кроме вырожденных случаев (на которые тебя упорно тянет), невозможно определить ДО выполнения. Именно поэтому в ПМ по дискриминатору АлгТД более одной ветки, под все необходимые случаи, возможные в рантайм. А ведь в реальности многие из этих веток могут быть "мертвыми", т.е. не быть вызванными ни разу. Как тебе такое "property of a programme we can determine without executing the program"?
VE>Мол, что (x:int){x==0}, что (x:int){x>0}, один чёрт int, 4 байта, да?
Да, значение дискриминатора (т.е. некое его представление) само имеет некий тип, а что? Тебя смущает, что этот тип тебе не доступен в общем случае? ИМХО, лишь для того, чтобы не ограничивать способ реализации. Но для случая встроенных интегральных типов Хаскеля — доступен. Т.е. для некоего мн-ва встроенных типов, для которых объявлено, что они являются АлгТД, прямо в спецификации указан способ представления дискриминаторов этих АлгТД. Теперь полегчало?
VE>Ну так и указатель любой 4 (или 8) байта, ан нет, типы-то разные!
Ну и каша... В одном и том же варианте все значения дискриминаторов представлены одним и тем же типом by design алгебраического типа. Т.е. заведомо совместимы. А указатели разных типов в С++ сделаны несовместимыми, в отличие от С, именно затем, чтобы процедуру реинтерпретации памяти описывать в коде явно через специально предназначенные синтаксические конструкции реинтерпретации памяти, а не через простое присвоение указателей как в С.
Здравствуйте, DarkGray, Вы писали:
DG>с точки зрения какой формальной логики ты утверждаешь, что там этого нет? DG>с точки зрения конструктивной логики там есть вся необходимая информация для построения разных типов и полиморфизма.
Я утверждаю с точки зрения конкретного языка (вернее семейства ML языков) программирования.
Для Standard ML 97 есть полное формальное описание как синтаксиса так и семантики, если нужна полная
математическая формализация ищи это описание.
FR>>Есть один единственный тип:
FR>>type test = Int of int | Float of float | String of string
DG>с точки зрения конструктивной логики (и наличия операций композиции и декомпозиции) — это как минимум 4 типа (вся необходимая информация есть), при необходимости можно построить и другие типы (в частности, type Number = Int of int | Float of float и т.д.)
Понятно пошла альтернативная терминология и логика тут я пас, на десятки страниц обсуждения
ни о чем нет времени.
Здравствуйте, VoidEx, Вы писали:
VE>Можно вообще все unsigned int на int поменять (и наоборот), только придётся ручками указывать, какой именно мы less хотим. VE>Т.е. они по сути оба strong typedef на одно и то же.
Именно строгий. Только это и позволяет использовать статический полиморфизм в операциях <, >.
Хотя, бывают и другие плюшки, например массив int в дотнете приводим к массиву uint, т.е. среда исполнения допускает такую реинтерпретацию памяти. А вот со ссылочными значениями уже обломс.
VE>Собственно, можно как раз про strong typedef и вспомнить. Неужто они определяет способ хранения в памяти, вводя новый тип?
Дык, представление значения типа в памяти — это не единственный признак типа. Один из. Прдеставь, что ты делаешь такой typedef в каком-нить интерпретаторе, где вся информация о типах нужна в момент исполнения. Тогда у тебя не будет возможности создать в памяти два одинаковых значения разного типа, т.к. будет всегда отличаться минимум одно поле — признак типа. Считай, что в статически-типизируемом происходит тоже самое, только признак типа "сокращается" компилятором. Но даже при компиляции статически-типизированного языка, признак типа сокращается не везде, а только там, где рантайм полиморфизм заведомо недоступен. Если же полиморфизм доступен в рантайм, то признак типа обязательно хранится вместе со значением.
VE>C-тип не умеет этого описывать. Как хранятся конкретные типы, описывает язык Си, а не тип. Типизировать программу можно вне зависимости от того, как хранятся данные в памяти. Не надо мешать всё в кучу.
на твой взгляд, какие типы умеют описывать хранение в памяти?
ASN.1 подойдет?
давай его тогда добавим к нашей надсистеме.
FR>Я утверждаю с точки зрения конкретного языка (вернее семейства ML языков) программирования. FR>Для Standard ML 97 есть полное формальное описание как синтаксиса так и семантики, если нужна полная FR>математическая формализация ищи это описание.
и какой смысл фиксировать такие общие определения, как: тип, типизация, полиморфизм, динамическая типизация и т.д. на основе кодогенерации конкретной реализации конкретного языка?
Здравствуйте, DarkGray, Вы писали:
FR>>Рантаймное ветвление при ПМ есть, почему ты и vdimas называете это динамической типизацией я не понимаю,
DG>дай формальное опредение, которое бы строгим образом отличало одно (динамическую типизацию) от другого (runtime-ветвление)? DG>причем чтобы это определение не зависело от конкретного ЯП, и было одинаково подходящим для произвольного языка.
DG>ззы DG>так как такого формального определения разницы дать нельзя, то я считаю — что это одно и тоже, а то что некоторые люди пытаются отличать одно от другого является чистой вкусовщиной и субъективизмом
Невозможность надо доказывать. То, что пока не привели такого определения, не означает, что его нет.
Например, навскидку, динамическая типизация:
Каждому типу a ставится в соответствие множество типов T свободных по a таких, для каждого t : T существуют примитивные параметрически полиморфные (с ограничением по множеству T) функции
cast : a -> t
dynamicCast : t -> Maybe a
При этом выполняется
backCast : a -> Prop
backCast x = dynamicCast (cast x : t) === Just x
Уточнение: сводобных по a означает, что t : T не содержит в своем выражении тип a. Т.е. например Either a b туда не подходит.
Не динамическая типизация (в случае, конечно, если они внутри не используют её некоторым образом):
left :: Either a b -> Maybe a
template <class T>
T * cast(Some<T> * p);
Динамическая типизация:
fromDyn :: (Typeable a) => Dynamic -> Maybe a
template <class T, class U>
U * myDynamicCast(T * p);
Т.е. в Haskell каждому Typeable a ставится в соотсветствие Dynamic, и есть функции туда-обратно с нужными свойствами:
toDyn :: Typeable a => a -> Dynamic
fromDyn :: Typeable a => Dynamic -> Maybe a
В Си++ такая "функция" dynamic_cast и встроенный каст в родителю.
Не является динамической типизацией функция
foo :: a -> Maybe b
foo _ = Just undefined
Так как результат не определён.
Не является динамической типизацией функция
bar :: a -> Maybe b
bar _ = Nothing
Так как (bar 4 :: Maybe Int) =/= (Just 4 :: Maybe Int)
Не является динамической типизацией функция
template <class T, class U>
T * notDyn(U * x) { return 0; }
Так как notDyn<int, int>(p) != 0
Не является динамической типизацией функция
template <class T, class U>
class NotDyn
{
public:
T * cast(U *) { return 0; }
};
template <class T>
class NotDyn<T, T>
{
public:
T * cast(T * x) { return x; }
};
Здравствуйте, DarkGray, Вы писали:
DG>и какой смысл фиксировать такие общие определения, как: тип, типизация, полиморфизм, динамическая типизация и т.д. на основе кодогенерации конкретной реализации конкретного языка?
Во первых не на основе кодогенерации, а на основе спецификации (или стандарта) языка, тут Standart ML как-раз
подходит лучше всех так как имеет полностью математически формализованную спецификацию.
Общие определения ни к чему кроме терминологического спора не приведут. Причина простая в большинстве языков
эти определения слишком размыты и для разных языков часто противоречивы.
Здравствуйте, VoidEx, Вы писали:
V>>Тогда нафига классы типов вообще нужны? VE>Чтобы не передавать Eq a явно. Правда, для этого вовсе не обязательно надо было городить классы типов.
А что можно?
V>>Например, обсуждаемый пример, где Nil и Cons — это совершенно независимые типы, а не конструкторы одного АлгТД. И где де-факто рекурсия была сделана на полиморфном аргументе, а не рекурсивном АлгТД. Т.е. классы типов позволяют использовать в алгоритмах независимые типы.
VE>Этот пример переписывается без использования классов типов один в один.
А обсуждаемый compile-time контроль длины массива остается?
Моя версия была такова:
V>>Тем более, что обсуждаемый пример можно переписать на АлгТД и обойтись без классов типов.
K>Нельзя. Потому, что нам нужны тайплевел вычисления, а не рантайм-проверка.
Можно, добавив фиктивные тайлевел вычисления, не участвующие в рантайм-вычислениях. Я имел ввиду организацию рекурсивного типа. Сейчас эта рекурсия выполнена на полиморфном аргументе, а можно было сделать явно на алгТД.
V>>Мне только что доказывали, что это не так. Хотя я именно настаиваю, что "унутре" реализация классов-типов может быть реализована на той же технике, что АлгТД. Почему и просил распечатку сишного промежуточного кода примера.
VE>Не знаю, кто вам что доказывал, но если этот пример таки написать на Си, у вас там будут те же самые проверки в том же объёме. Cons у вас будет не шаблоном, а struct Cons { int value; void * p; } и т.п. VE>Статическую проверку можно будет наложить шаблоном и кастами void* <-> T*
VE>На исходном Си++ примере же у нас кодогенерация, которая не даёт тех же возможностей, что и Haskell, но зато избавлена от проверок. Ну дак и на TemplateHaskell это можно сделать точно так же. Без проверок.
VE>Итого: либо оба примера работают, как хотел МигМит, с одинаковым кол-вом проверок, либо оба не используют проверки, как Си++, но и никакой вводимой длины списка не будет, а только определённая в compile-time.
+1000
спасибо за полноценное пояснение происходящего в рантайм, но вопрос насчет compile-time в силе.
V>>Таки нет. АлгТД имеет вполне конкретное определение. А тот факт, что классы типов конкретно в Хаскеле, с его, скажем так, особенностью представления модулей, вполне можно выразить через неявные АлгТД — это частность, которая может исчезнуть при другом представлении модулей. Просто сейчас компиляторам доступен "исходник" (пусть даже в распаршенном виде) всех используемых модулей, что можно в процессе компиляции статически сгенерить АлгТД по всем инстансам класса.
VE>Это шутка что ли или непонимание?
... VE>Что теперь? Туплы и ФВП у нас работают тоже благодаря особенностям представления модулей?
Я имел ввиду, что компилятор "видит" все инстансы классов типов из зависимых модулей.
Здравствуйте, DarkGray, Вы писали:
DM>>Ну так речь шла о типизации, а не о типе.
DG>если в понятие типа упоминается о способе хранения в памяти, а в более сложном понятии (типизация или type system) — этой составляющей нет, то можно сделать вывод, что определение сложного понятия как минимум не полное.
По-твоему, всякое определение должно включать в себя определения и подробности всех используемых терминов? Это нереально. Человечество придумало другой способ, получше: использовать лишь названия терминов, определения которых даются отдельно.
DG>>>, во-вторых: это ужасное определение: определение должно определять понятие через более простые, а в данном случае — определение элементарного понятия "type system" идет через такиие неопределяемые понятия как: syntactic, framework, classifying, phrases, kind, compute, according. DG>>>можно получить строгое формализованное определение всех перечисленных понятий?
DM>>Можно. А нужно?
DG>строго необходимо, если стоит задача получить корректное описание реальности.
Ок, займусь завтра. Только как бы это не вылилось в просьбы с твоей стороны дать определения всем-всем словам русского и английского языков, так мы нескоро закончим. Я (как и цитируемый в вики Пирс) надеялся на наличие у собеседников каких-то общих знаний, но видимо зря.
DM>>Это одна структура в Си, содержащая внутри union. Она трактуется по-разному в зависимости от значения определенного поля.
DG>здесь неявно подразумевается, что одна структура в C — это строго один математических тип. DG>из какого определения это следует?
Из определения структур в языке Си.
DM>>Я и говорю, подходов к определению может быть много. DG>определения все одинаковые?, или можно их классифицировать чем они лучше/хуже по тем или иным признакам?
Здравствуйте, vdimas, Вы писали:
VE>>И if именно это и делает.
V>Там, где в рамках статически-типизированного языка не выполняется реинтерпретация памяти, то if этого не делает ни разу.
Делает, делает.
VE>>Не путайте то, какие байтики лежат, с типом. В случае указателя конкретное устройство значения одно и то же — указатель, но тип тем не менее разный.
V>Это ты путаешь. Одинаковое устройство даже двух объявленных одинаково типов не гарантируется в том же С++. А в плане указателей (при чем тут они, кстати?), если работаем именно со значением указателя, а не с указываемой областью памяти, то одинаковое устройство указателей проявляется в полной мере — мы можем присвоить void * значение типизированного указателя, преобразовать в число, получить из числа и т.д. Попробуй преобразовать в число, скажем, struct A {}.
Типы Base * и Child * — разные. Не Base и Child, а именно Base * и Child *. Где тут реинтепретация памяти?
VE>>
VE>>Formally, a type can be defined as "any property of a programme we can determine without executing the program"
VE>>Вы же почему-то под типом подразумеваете какое-то внутреннее представление.
V>Почему нет, если речь идет непосредственно об этом представлении? Например, когда мы обсуждаем компилятор статически-типизируемого языка, а не некий интерпретатор.
Потому, что тогда мы придём к вырожденному случаю: при любом ветвлении программа ведёт себя с памятью по-разному.
Т.е. проверка на if (x == 0) меняет её работу с памятью, т.е. приводит к различной её интерпретации.
И именно поэтому важно не то, что с памятью работают иначе (ибо это всегда так), а то, как на это дело наложена система типов.
V>И да, содержимое АлгТД, кроме вырожденных случаев (на которые тебя упорно тянет), невозможно определить ДО выполнения. Именно поэтому в ПМ по дискриминатору АлгТД более одной ветки, под все необходимые случаи, возможные в рантайм. А ведь в реальности многие из этих веток могут быть "мертвыми", т.е. не быть вызванными ни разу. Как тебе такое "property of a programme we can determine without executing the program"?
Мёртвыми могут быть ветки и в банальном Си. Иногда компилятор это даже умеет определять и оптимизировать. К типизации это отношения не имеет.
Или что, назовём динамической типизацией лишние if, когда согласно алгоритму в этот if мы никогда не попадём (но при этом выяснить это в compile-time = решить проблему останова)?
VE>>Мол, что (x:int){x==0}, что (x:int){x>0}, один чёрт int, 4 байта, да?
V>Да, значение дискриминатора (т.е. некое его представление) само имеет некий тип, а что? Тебя смущает, что этот тип тебе не доступен в общем случае? ИМХО, лишь для того, чтобы не ограничивать способ реализации. Но для случая встроенных интегральных типов Хаскеля — доступен. Т.е. для некоего мн-ва встроенных типов, для которых объявлено, что они являются АлгТД, прямо в спецификации указан способ представления дискриминаторов этих АлгТД. Теперь полегчало?
Чего? Ты читаешь, что я пишу? Причём тут АлгТД вообще?
Давай перепишу иначе:
(x:int){x > 10} и (x:int) { 10 * x + 23 < 2332 } — это разные типы. Но по-твоему получается, что нет.
Нотация (x:t){f(x)} означает, что x принадлежит подмножеству t такому, что выполняется f(x). Это тип. Никакой f не вычисляется в runtime и даже не существует.
Типы разные, представление — абсолютно одинаковое.
VE>>Ну так и указатель любой 4 (или 8) байта, ан нет, типы-то разные!
V>Ну и каша... В одном и том же варианте все значения дискриминаторов представлены одним и тем же типом by design алгебраического типа. Т.е. заведомо совместимы. А указатели разных типов в С++ сделаны несовместимыми, в отличие от С, именно затем, чтобы процедуру реинтерпретации памяти описывать в коде явно через специально предназначенные синтаксические конструкции реинтерпретации памяти, а не через простое присвоение указателей как в С.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, VoidEx, Вы писали:
V>>>Тогда нафига классы типов вообще нужны? VE>>Чтобы не передавать Eq a явно. Правда, для этого вовсе не обязательно надо было городить классы типов.
V>А что можно?
implicit arguments
V>>>Например, обсуждаемый пример, где Nil и Cons — это совершенно независимые типы, а не конструкторы одного АлгТД. И где де-факто рекурсия была сделана на полиморфном аргументе, а не рекурсивном АлгТД. Т.е. классы типов позволяют использовать в алгоритмах независимые типы.
VE>>Этот пример переписывается без использования классов типов один в один.
V>А обсуждаемый compile-time контроль длины массива остается?
Да.
V>>>Таки нет. АлгТД имеет вполне конкретное определение. А тот факт, что классы типов конкретно в Хаскеле, с его, скажем так, особенностью представления модулей, вполне можно выразить через неявные АлгТД — это частность, которая может исчезнуть при другом представлении модулей. Просто сейчас компиляторам доступен "исходник" (пусть даже в распаршенном виде) всех используемых модулей, что можно в процессе компиляции статически сгенерить АлгТД по всем инстансам класса.
V>Я имел ввиду, что компилятор "видит" все инстансы классов типов из зависимых модулей.
Считайте, что они импортируются неявно. Система типов от этого не страдает.
Здравствуйте, DarkGray, Вы писали:
DG>пока ты копируешь определения из википедии — никакого сознания нет, есть лишь тот самый автомат из китайской комнаты, который механически подставляет необходимую ссылку на википедию, когда встречает ключевые слова. DG>сознание определяют как умение выстраивать логические цепочки и гибкое адаптирование к контексту. DG>при копировании определения из вики — ни первого, ни второго — нет.
Во-первых, не надо путать сознание (consciousness) и интеллект/разум (intelligence), это очень разные вещи. Во-вторых, когда я цитирую википедию, я опираюсь на общую базу знаний и надеюсь, что используемые там слова собеседникам известны. В противном случае коммуникация крайне трудна. В-третьих, китайская комната как раз показывает, что даже демонстрация выстраивания логических цепочек не позволяет определить наличие "настоящего" разума. Зато логические ляпы вроде твоего позволяют показать недостаток разумности.
Здравствуйте, DarkGray, Вы писали:
DM>>Никакой специализации компилятор не сделает, на эффективность dummy_id твой код не повлияет, там внутри по-прежнему будет по 2 if'a.
DG>можно ли при этом сгенерировать более эффективный код? хотя бы руками?
В том конкретном случае, когда все аргументы известны при компиляции, можно суперкомпиляцией сразу получить программу, выводящую ответ, все вычисления выкинув.
Здравствуйте, VoidEx, Вы писали:
VE>Отличие в том, что instance может быть только один, и передаётся он неявно.
Именно, достаточен один экземпляр таблицы ф-ий, который компилятор построит сам.
Странно, что мои аналогичные предположения, как это может быть реализовано, были оспорены здесь: http://www.rsdn.ru/forum/decl/4675175.1.aspx