Spec-Zone.ru › Haskell 9

System.IO.Unsafe

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

Содержание

  • Операции Unsafe IO

Описание

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

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

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

Это «задняя дверь» в 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. Поэтому будьте осторожны!

ПРЕДУПРЕЖДЕНИЕ: Если вы ищете «способ получить String из 'IO String'», то unsafePerformIO — не тот путь. Изучите нотацию do и элемент синтаксиса <- прежде чем продолжить.

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

Эта версия unsafePerformIO более эффективна, поскольку она опускает проверку того, что операция ввода-вывода выполняется только одним потоком. Следовательно, при использовании unsafeDupablePerformIO, существует вероятность, что операция ввода-вывода может быть выполнена несколько раз (на многопроцессорной системе), и поэтому необходимо гарантировать, что она даёт одинаковые результаты каждый раз. Возможно, что одна из дублированных операций ввода-вывода будет выполнена частично и затем прервана в середине без поднятия исключения. Поэтому функции, такие как 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/9.12.1/docs/libraries/base-4.21.0.0-8e62/System-IO-Unsafe.html

Spec-Zone.ru

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