[Haskell-cafe] Weird defaulting on newEmptyTMVar
Viktor Dukhovni
ietf-dane at dukhovni.org
Sun Feb 10 10:07:17 UTC 2019
On Sun, Feb 10, 2019 at 12:24:52AM -0300, Ruben Astudillo wrote:
> Playing on ghci I encountered the following type
>
> GHCi, version 8.6.3: http://www.haskell.org/ghc/ :? for help
> Prelude> :m +Control.Concurrent.STM
> Prelude Control.Concurrent.STM> var1 <- atomically $ newEmptyTMVar
> Prelude Control.Concurrent.STM> :t var1
> var1 :: TMVar GHC.Types.Any
> Prelude Control.Concurrent.STM>
Much simpler:
$ ghci
GHCi, version 8.6.3: http://www.haskell.org/ghc/ :? for help
Prelude> let v = Nothing
Prelude> :t v
v :: Maybe a
Prelude> v <- return Nothing
Prelude> :t v
v :: Maybe GHC.Types.Any
This looks like let-bound polymorphism in action. But the two types
of "Nothing" are representationally equivalent, so you can write:
Prelude> :m + Unsafe.Coerce
...> case unsafeCoerce v of { Just 1 -> True; _ -> False }
False
...> case unsafeCoerce v of { Just 'a' -> True; _ -> False }
False
The case of MVars case is more complicated:
...> :m + Control.Concurrent.MVar
...> v <- newEmptyMVar
...> :t v
v :: MVar GHC.Types.Any
...> putMVar (unsafeCoerce v) (1 :: Int)
...> x <- readMVar v
...> :t x
x :: GHC.Types.Any
...> unsafeCoerce x :: Int
1
The issues become a bit more clear if we replace the "<-" with
unsafePerformIO:
...> :m + System.IO.Unsafe
...> let v = unsafePerformIO newEmptyMVar
...> :t v
v :: MVar a
...> putMVar v (1 :: Int)
...> let x = unsafePerformIO (readMVar v)
...> :t x
x :: a
So now we seem to have an "x" that is of any type and yet is not
bottom! We secretly know it is an Int:
...> unsafeCoerce x :: Int
1
But how is GHC supposed to type check that? So without opportunities
for type inference, and with no applicable annotations, "Any" seems
quite right, with the only way to get a value out being "unsafeCoerce".
If you want a more friendly empty MVar via the REPL, you need to
add a type annotation:
...> v <- newEmptyMVar :: IO (Mvar Int)
...> :t v
v :: MVar Int
In compiled code the MVar's type can often be inferred from the
context in which "v" is used, and the type annotation is then
not required.
--
Viktor.
More information about the Haskell-Cafe
mailing list