Основная проблема заключается в том, что ограничения вашей подписи делают полученный модуль слишком непрозрачным. Когда вы ограничиваете свой результат функтора:
module FromToString (S:ToString) : Printable = ...
вы делаете тип t
абстрактным типом, который может использоваться только функцией to_string
и никогда не создается. Другими словами, модуль типа Printable
сам по себе непригоден.
При запуске с функтором очень часто полезно посмотреть на тип модуля, выведенный компилятором для результирующего модуля. В случае FromToString
это выглядит так:
module FromToString (S:ToString) : sig
type t = S.t
val print: t -> unit
end = ...
Вы можете видеть, что предполагаемый тип модуля результата
sig
type t = S.t
val print: t -> unit
end
очень похож на Printable
за исключением того, что теперь тип t
равен типу t
модуля аргумента S
.
Таким образом, можно повторно использовать Printable
для записи полного типа модуля результата, добавив равенство типов с ограничением with
:
module FromToString (S:ToString): Printable with type t = S.t = struct
type t = S.t
let print a = print_string ( S.to_string a)
end
Появляется та же проблема для IntToString и может быть исправлена аналогичным образом:
module IntToString : ToString with type t = int =
struct
type t = int
let to_string = string_of_int
end
Тогда ошибка компилятора исчезнет:
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
Я не думаю, что существуют любые соображения производительности кроме возможной разницы между и неподписанной арифметикой со знаком на уровне процессора, но в той точке, я думаю, что различия спорны.
Большее различие находится в совместимости с CLS, поскольку неподписанные типы не CLS-совместимы как не, все языки поддерживают их.
Я не провел исследования по вопросу в.NET, но в былые дни Win32/C++, если бы Вы хотели бросить "интервал со знаком" к "со знаком длинный", то CPU должен был выполнить op для расширения знака. Для кастинга "неподписанного интервала" к "неподписанный длинный" это просто имело нуль материала в старших байтах. Сбережения были на порядке нескольких тактов (т.е. необходимо будет сделать это миллиарды времен, чтобы иметь ровное заметное различие),
Нет никакого различия, мудрая производительность. Простые целочисленные вычисления известны, и современный CPU высоко оптимизированы для выполнения их быстро.
Эти типы оптимизации редко стоят усилия. Используйте тип данных, который наиболее подходит для задачи, и оставьте его в этом. Если эта вещь так как касания база данных, Вы могли бы, вероятно, найти дюжину тонких настроек в дизайне DB, синтаксисе запроса или стратегии индексации, которая сместит оптимизацию кода в C# несколькими сотнями порядков величины.
Его попытка выделить тот же объем памяти так или иначе (хотя тот может сохранить большее значение как не оставляющее свободное место для знака). Таким образом, я сомневаюсь, что Вы будете видеть различие 'в производительности', если Вы не будете использовать большие значения / отрицательные величины, которые заставят одну опцию или другой взрываться.
это действительно не относится к производительности скорее требования для счетчика цикла.
Предварительные случаи там были большим количеством повторений для завершения
Console.WriteLine(Int32.MaxValue); // Max interation 2147483647
Console.WriteLine(UInt32.MaxValue); // Max interation 4294967295
Неподписанный интервал может быть там по причине.