Spec-Zone.ru › Haskell 9

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

StaticPointers
Since:

7.10.1

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

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

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

Статические указатели были впервые предложены в статье Towards Haskell in the cloud, Джеффа Эпштейна, Эндрю П. Блэка и Саймона Пейтона-Джонса, в трудах 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.12.1/docs/users_guide/exts/static_pointers.html

Spec-Zone.ru

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