Spec-Zone.ru › Haskell 8

System.IO.Unsafe

Авторские права (c) Университет Глазго 2001
Лицензия BSD-стиль (см. файл libraries/base/LICENSE)
Поддерживающий libraries@haskell.org
Стабильность предварительная
Переносимость переносимый
Безопасный Haskell Небезопасный
Язык Haskell2010

Содержание

  • Небезопасные IO операции

Описание

«Небезопасные» операции ввода-вывода.

Небезопасные IO операции

unsafePerformIO :: IO a -> a Исходный код

Это «задняя дверь» в IO монаду, позволяющая выполнять IO вычисления в любое время. Для безопасности вычисление IO должно быть свободно от побочных эффектов и независимо от своей среды.

Если вычисление ввода-вывода, обернутое в unsafePerformIO, выполняет побочные эффекты, то относительный порядок выполнения этих побочных эффектов (относительно основного потока ввода-вывода или других вызовов unsafePerformIO) неопределён. Кроме того, при использовании unsafePerformIO для создания побочных эффектов, необходимо принять следующие меры предосторожности, чтобы гарантировать выполнение побочных эффектов столько раз, сколько ожидается. Обратите внимание, что эти меры предосторожности необходимы для GHC, но могут быть недостаточными, и другие компиляторы могут потребовать других мер предосторожности:

  • Используйте {-# NOINLINE foo #-} как директиву для любой функции foo, которая вызывает unsafePerformIO. Если вызов инлайнится, ввод-вывод может быть выполнен более одного раза.
  • Используйте флаг компилятора -fno-cse для предотвращения выполнения общего устранения подвыражений в модуле, которое может объединить два побочных эффекта, которые должны были быть отдельными. Хорошим примером является использование нескольких глобальных переменных (например, test в примере ниже).
  • Убедитесь, что либо вы отключили плавание let (-fno-full-laziness), либо вызов unsafePerformIO не может «выплыть» за пределы лямбда-выражения. Например, если вы говорите: f x = unsafePerformIO (newIORef []) , у вас может быть только одна общая ячейка ссылок для всех вызовов f. Лучше было бы f x = unsafePerformIO (newIORef [x]) , так как теперь он не может выплыть за пределы лямбда-выражения.

Менее известно, что unsafePerformIO не является безопасным с точки зрения типов. Например:

    test :: IORef [a]
    test = unsafePerformIO $ newIORef []

    main = do
            writeIORef test [42]
            bang <- readIORef test
            print (bang :: [Char])

Эта программа вызовет сбой. Эта проблема с полиморфными ссылками хорошо известна в сообществе ML и не возникает при обычном монадическом использовании ссылок. Нет простого способа сделать её невозможной после использования unsafePerformIO. Действительно, можно написать coerce :: a -> b с помощью unsafePerformIO. Так что будьте осторожны!

unsafeDupablePerformIO :: IO a -> a Исходный код

Эта версия unsafePerformIO более эффективна, так как она опускает проверку, что IO выполняется только одним потоком. Следовательно, при использовании unsafeDupablePerformIO, существует вероятность того, что действие IO может быть выполнено несколько раз (на многопроцессорной системе), и, следовательно, вы должны убедиться, что оно даёт те же результаты каждый раз. Может даже произойти так, что одно из дублированных действий ввода-вывода выполнится лишь частично, а затем прервётся посредине без возникновения исключения. Поэтому функции, такие как bracket, не могут использоваться безопасно в unsafeDupablePerformIO.

С версии: base-4.4.0.0

unsafeInterleaveIO :: IO a -> IO a Исходный код

unsafeInterleaveIO позволяет отложить выполнение вычисления IO лениво. При передаче значения типа IO a, IO будет выполнено только тогда, когда потребуется значение a. Это используется для реализации ленивого чтения файлов, см. hGetContents.

unsafeFixIO :: (a -> IO a) -> IO a Исходный код

Несколько более быстрая версия fixIO, которая может быть небезопасной для использования с несколькими потоками. Небезопасность возникает при использовании следующим образом:

 unsafeFixIO $ \r -> do
    forkIO (print r)
    return (...)

В этом случае дочерний поток получит исключение NonTermination вместо ожидания вычисления значения r.

С версии: base-4.5.0.0

© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/8.10.2/docs/html/libraries/base-4.14.1.0/System-IO-Unsafe.html

Spec-Zone.ru

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