Какова связь между распакованными типами и строгостью?

Распакованные типы, такие как Int#и строгие функции, как f (!x) = ..., это что-то другое, но я вижу концептуальное сходство - они каким-то образом запрещают громы и лень. Если бы Haskell был строгим языком, таким как Ocaml, каждая функция была бы строгой, а все типы были распакованы. Какова связь между распакованными типами и соблюдением строгости?

3 ответа

Решение

Распакованные данные в штучной упаковке

Для поддержки параметрического полиморфизма и лени, по умолчанию типы данных Haskell представлены единообразно как указатель на замыкание в куче со структурой, подобной этой:

альтернативный текст

Это "коробочные" значения. Распакованный объект представляется непосредственно значением непосредственно, без какого-либо косвенного обращения или закрытия. Int в штучной упаковке, но Int# распакован

Ленивые значения требуют представления в штучной упаковке. Строгие значения этого не делают: они могут быть представлены либо как полностью оцененные замыкания в куче, либо как примитивные неупакованные структуры. Обратите внимание, что тегирование указателя - это оптимизация, которую мы можем использовать для объектов в штучной упаковке, чтобы кодировать конструктор в указателе на замыкание.

Отношение к Строгости

Обычно распакованные значения генерируются специальным образом компиляторами функционального языка. Однако в Haskell распакованные значения являются особыми. O ни:

  1. у них другой вид, #;
  2. можно использовать только в специальных местах; а также
  3. они не подняты, поэтому не представлены как указатель на значение кучи.

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

Так что особые распакованные типы, такие как Int#, Double#, действительно представлены как double или int на машине (в C-записи).

Анализ строгости

Отдельно GHC проводит анализ строгости регулярных типов Haskell. Если использование значения установлено как строгое - то есть оно никогда не может быть "неопределенным" - оптимизатор может заменить все виды использования обычного типа (например, Int) с распакованным (Int#), так как знает, что использование Int всегда строгий, и, следовательно, замена на более эффективный (и всегда строгий) тип Int# безопасно.

Конечно, у нас могут быть строгие типы без распакованных типов, например, полиморфный список со строгим элементом:

data List a = Empty | Cons !a (List a)

строг в своих элементах, но не представляет их как распакованные значения.

Это также указывает на ошибку, которую вы сделали со строгими языками, такими как OCaml. Им по-прежнему необходимо поддерживать полиморфизм, поэтому либо они обеспечивают единообразное представление, либо они специализируют типы данных и функции для каждого типа. GHC по умолчанию использует унифицированное представление, как и OCaml, хотя GHC теперь может также специализировать типы и функции (например, шаблоны C++).

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

data Foo a = Foo !a !a

имеет два строгих поля

data Bar a = Bar {-# UNPACK #-} !Int !a

имеет два строгих поля, но первое не занято.

В конечном итоге причина того, что распакованные типы являются (обязательно) строгими, заключается в том, что негде хранить thunk, поскольку они представляют собой просто плоские, тупые данные в этой точке.

Аргументы любых типов могут быть сделаны "строгими", но единственными распакованными типами, которые имеют соответствующие упакованные типы, являются Char#, Int#, Word#, Double# а также Float#,

Если вы знаете языки низкого уровня, такие как C, это легче объяснить. Распакованные типы похожи int, doubleи т. д., и в штучной упаковке типа как int*, double*и т. д. Когда у вас есть intВы уже знаете все значение, как оно представлено в битовой комбинации, поэтому оно не ленивое. Он должен быть строгим, так как все значения int действительны и не ⊥.

Однако, учитывая int* Вы можете выбрать разыменование указателя позже, чтобы получить фактическое значение (таким образом, ленивое), и возможно иметь недопустимые указатели (они содержат ⊥, то есть не являются строгими).

Другие вопросы по тегам