Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the Haskell compiler "know" that IO cannot be unwrapped?

Obviously, the following function is impossible, because it is impossible to unwrap an IO value permanently (ignoring unsafePerformIO or similar):

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

However, similar functions such as the following are possible:

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

I fully understand the reasoning behind why #2 is possible but #1 is not, but I do not understand how. Can I also make my own types that are not unwrappable?

like image 937
markasoftware Avatar asked Nov 27 '18 00:11

markasoftware


People also ask

How does Io work in Haskell?

IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.

How is Haskell IO pure?

Haskell is a pure language Being pure means that the result of any function call is fully determined by its arguments. Procedural entities like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell.

What is returns Haskell?

return is actually just a simple function in Haskell. It does not return something. It wraps a value into a monad. Looks like return is an overloaded function.

What is IO Int?

A good way to think about this is: an IO Int is the specification for a program that produces an Int when executed by the Haskell runtime. The way to use an IO Int program specification is to build it into a larger program specification, which you then feed to the Haskell runtime by calling it main . 5. rstd • 7 yr. ...


2 Answers

Just and Nothing are data constructors for the type Maybe a. IO has no data constructors to speak of (in GHC it actually has constructors but they're really implementation details of GHC, and other implementations might define IO differently).

unwrapIO (IO str) = str doesn't make sense in the same way unwrapMaybe (Maybe str) = str doesn't make sense. IO and Maybe are not data constructors, so you cannot pattern-match on them.

like image 161
Li-yao Xia Avatar answered Sep 29 '22 07:09

Li-yao Xia


It's because the data constructor of IO is not exported. I mean, you can think it's not exported.

You can prevent your own type from being unwrapped by using the same strategy.

module Test (Test, test) where

data Test a = MkTest a

test :: a -> Test a
test = MkTest

You can create a value of Test using test, but you cannot unwrap it using pattern-match because MkTest is not exported.

like image 41
snak Avatar answered Sep 29 '22 05:09

snak