-
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
Кроме того, для типа 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))