Как компилятор Haskell «узнает», что IO не может быть развернут? - PullRequest
0 голосов
/ 27 ноября 2018

Очевидно, что следующая функция невозможна, поскольку невозможно постоянно развернуть значение IO (игнорируя unsafePerformIO или подобное):

unwrapIO :: IO String -> String
unwrapIO (IO str) = str

Однако возможны аналогичные функции, такие как следующие:

unwrapJust :: Maybe String -> String
unwrapJust (Just str) = str
unwrapJust Nothing = "ignore this plz"

Я полностью понимаю причину, по которой № 2 возможен, но № 1 нет, но я не понимаю, как.Могу ли я также создавать свои собственные типы, которые не могут быть распакованы?

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Это потому, что конструктор данных IO не экспортируется.Я имею в виду, вы можете думать, что он не экспортируется.

Вы можете предотвратить развертывание вашего собственного типа, используя ту же стратегию.

module Test (Test, test) where

data Test a = MkTest a

test :: a -> Test a
test = MkTest

Вы можете создать значение Test, используяtest, но вы не можете развернуть его с помощью сопоставления с образцом, потому что MkTest не экспортируется.

0 голосов
/ 12 января 2019

Я считаю, что хотя существующие ответы в основном верны, есть более глубокая причина, по которой IO нельзя развернуть. Концептуально , type IO a = RealWorld -> (a, RealWorld).IO - это тип функции (в реальных реализациях, скрытых за оболочкой нового типа или эквивалентным механизмом).

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

Монадический экземпляр, конечно, может просто передавать RealWorld как состояние, вроде StateT и вконец, единственный когда-либо созданный экземпляр - при запуске программы, затем он передается между IO s.

Возвращаясь к реальности снова, это (снова) ложь.На самом деле вы можете получить экземпляр RealWorld и можете вызвать действие IO a «раньше времени».Есть функция, которая делает именно то, что вы просили.Он называется System.IO.Unsafe.unsafePerformIO :: IO a -> a, хотя по какой-то причине он находится в небезопасном пакете.

0 голосов
/ 27 ноября 2018

Just и Nothing являются конструкторами данных для типа Maybe a.IO не имеет конструкторов данных, о которых можно было бы говорить (в GHC на самом деле есть конструкторы, но они действительно представляют детали реализации GHC, а другие реализации могут определять IO по-разному).

unwrapIO (IO str) = str несмысл в том же духе unwrapMaybe (Maybe str) = str не имеет смысла.IO и Maybe не являются конструкторами данных, поэтому вы не можете сопоставить их с шаблоном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...