Spec-Zone.ru › Haskell 9

6.15.3. Статические указатели

StaticPointers
Начиная с:

7.10.1

Разрешает использование синтаксиса статических указателей.

Расширение языка StaticPointers добавляет новую синтаксическую форму static e, которая обозначает ссылку на замкнутое выражение ⟨e⟩. Эта ссылка является стабильной и переносимой: она остаётся действительной в разных процессах, возможно, на разных машинах. Таким образом, процесс может создать ссылку и отправить её другому процессу, который сможет разрешить её в ⟨e⟩.

При включённом этом расширении static больше не является допустимым идентификатором.

Статические указатели впервые были предложены в статье К Haskell в облаке, Jeff Epstein, Andrew P. Black и Simon Peyton-Jones, материалы 4-го симпозиума ACM по Haskell, с. 118–129, ACM, 2011.

6.15.3.1. Использование статических указателей

Каждой ссылке назначается ключ, с помощью которого её можно найти во время выполнения функцией GHC.StaticPtr.unsafeLookupStaticPtr. Она использует глобальную неизменяемую таблицу, называемую таблицей статических указателей. Компилятор добавляет в эту таблицу записи для всех статических форм, обнаруженных в скомпонованных модулях. Значение можно получить из ссылки с помощью GHC.StaticPtr.deRefStaticPtr.

Тело e выражения static e должно быть замкнутым выражением. Выражение называется замкнутым, если все его свободные (типовые) переменные замкнуты. Переменная является замкнутой, если она связана let-выражением с замкнутым выражением, а её тип также замкнут. Тип является замкнутым, если у него нет свободных переменных.

Допустимы следующие варианты:

inc :: Int -> Int
inc x = x + 1

ref1 = static 'a'
ref2 = static inc
ref3 = static (inc 1)
ref4 = static ((\x -> x + 1) (1 :: Int))
ref5 = static (let x = 'a' in x)
ref6 = let x = 'a' in static x

Следующие определения, напротив, будут отклонены:

ref7 y = let x = y in static x    -- x is not closed
ref8 y = static (let x = 1 in y)  -- y is not let-bound
ref9 (y :: a) = let x = undefined :: a
                 in static x      -- x has a non-closed type

Примечание

Модули, загруженные в GHCi командой :load, могут использовать StaticPointers и выражения static, однако инструкции, введённые в REPL, этого делать не могут. Это ограничение GHCi; подробности см. в #12356.

Примечание

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

6.15.3.2. Статическая семантика статических указателей

Неформально, если у нас есть замкнутое выражение

e :: forall a_1 ... a_n . t

то статическая форма имеет тип

static e :: (IsStatic p, Typeable a_1, ... , Typeable a_n) => p t

Статическая форма определяет значение типа StaticPtr t, однако, как и OverloadedLists и OverloadedStrings, это литеральное выражение перегружено, чтобы позволить неявно поднимать StaticPtr до другого типа с помощью класса IsStatic:

class IsStatic p where
    fromStaticPtr :: Typeable a => StaticPtr a -> p a

Единственный предопределённый экземпляр — очевидный, ничего не выполняющий:

instance IsStatic StaticPtr where
    fromStaticPtr sptr = sptr

См. GHC.StaticPtr.IsStatic.

Кроме того, для типа t требуется экземпляр Typeable. Поэтому следующие варианты недопустимы:

static id                      -- No Typeable instance for (a -> a)
static Control.Monad.ST.runST  -- No Typeable instance for ((forall s. ST s a) -> a)

Тем не менее при надлежащем использовании типов-обёрток указанные выше ограничения не приводят к потере общности:

{-# LANGUAGE ConstraintKinds           #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE Rank2Types                #-}
{-# LANGUAGE StandaloneDeriving        #-}
{-# LANGUAGE StaticPointers            #-}

import Control.Monad.ST
import Data.Typeable
import GHC.StaticPtr

data Dict c = c => Dict

g1 :: Typeable a => StaticPtr (Dict (Show a) -> a -> String)
g1 = static (\Dict -> show)

data Rank2Wrapper f = R2W (forall s. f s)
  deriving Typeable
newtype Flip f a s = Flip { unFlip :: f s a }
  deriving Typeable

g2 :: Typeable a => StaticPtr (Rank2Wrapper (Flip ST a) -> a)
g2 = static (\(R2W f) -> runST (unFlip f))

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.14.1/docs/users_guide/exts/static_pointers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API