
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.