[Haskell-cafe] Weird defaulting on newEmptyTMVar
Ian Denhardt
ian at zenhack.net
Sun Feb 10 19:04:26 UTC 2019
Quoting Ruben Astudillo (2019-02-09 22:24:52)
> Dear list
>
> 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>
>
> I would think `var1 :: TMVar a` as the documentation says it should.
> Reading on `GHC.Types` `Any` seems to be a type family related to some
> laws on `unsafeCoerce`. Can anybody explain me why is this sensible
> defaulting and how to obtain the expected result?
There's a fine distinction here: The docs don't specify:
`var1 :: forall a. TMVar a`
but rather:
`newEmptyTMVar :: forall a. STM (TMVar a)`.
I've inserted the explicit foralls for clarity.
Suppose the behavior was as you expected (I'll use regular MVars just
for brevity):
var <- newEmptyMVar
ghci> :t var
var :: forall a. MVar a
Then, because the variable is polymorphic, we should be able to do:
putMVar var "Hello"
and, we should also be able to do:
putMVar var 43
But this is clearly unsafe, because we've put values of two different
types in the same MVar!
In a full program, what would most likely happen is, the first time GHC
sees a use of putMVar, it constrains the type variable to match that
type. In something like this:
do
var <- newEmptyMVar
putMVar var "hello"
...
On the second line, GHC constrains the `a` type variable to be `String`,
and so marks that particular use of `newEmptyMVar` as having been used
at type `IO (MVar String)`.
If we don't actually do anything with the MVar, like:
someAction = do
var <- newEmptyMVar
...
return var
then `someAction` is inferred to be of type `forall a. IO (MVar a)`,
just like `newEmptyMVar` itself. The constraining will happen wherever
the MVar actually ends up getting used.
But, in the REPL, we're in this weird state where we have access to the
variable and can as what it's type is, but then things can happen
*later* that will force GHC to change the answer.
-Ian
More information about the Haskell-Cafe
mailing list