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?
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.
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.
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.
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. ...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With