
Hi, There are obviously a lot of cool tricks you can do with phantom parameters, but they are all lost when you start looking at a `MVar` holding a type with a phantom parameter. Is there any way to track this type-level information, while still being able to write/read values from multiple threads? ======= Georgi

On Sun, Apr 28, 2019 at 12:45:24PM +0300, Georgi Lyubenov wrote:
There are obviously a lot of cool tricks you can do with phantom parameters, but they are all lost when you start looking at a `MVar` holding a type with a phantom parameter.
That's an intriguing statement. Why are they lost?

On Sun, Apr 28, 2019 at 10:56:42AM +0100, Tom Ellis wrote:
On Sun, Apr 28, 2019 at 12:45:24PM +0300, Georgi Lyubenov wrote:
There are obviously a lot of cool tricks you can do with phantom parameters, but they are all lost when you start looking at a `MVar` holding a type with a phantom parameter.
That's an intriguing statement. Why are they lost?
The types don't look lost to me at first blush: ghci> import Control.Concurrent.MVar ghci> import Data.Proxy ghci> let p = Proxy :: Proxy Int ghci> m <- newMVar p ghci> let q = Proxy :: Proxy Char ghci> x <- readMVar m ghci> q == x <interactive>:20:6: error: • Couldn't match type ‘Int’ with ‘Char’ Expected type: Proxy Char Actual type: Proxy Int • In the second argument of ‘(==)’, namely ‘x’ In the expression: q == x In an equation for ‘it’: it = q == x ghci> modifyMVar_ m $ const $ return q <interactive>:25:17: error: • Couldn't match type ‘Char’ with ‘Int’ Expected type: Proxy Int -> IO (Proxy Int) Actual type: Proxy Int -> IO (Proxy Char) • In the second argument of ‘($)’, namely ‘const $ return q’ In the expression: modifyMVar_ m $ const $ return q In an equation for ‘it’: it = modifyMVar_ m $ const $ return q -- Viktor.

Sorry! I phrased my question very pooryl and/or was not clear on what I exactly I had difficulty with. I have an external "machine" M, with some states and two IO actions that operate on M - A and B. A changes the state of the machine to "ready", and I want to enforce at the type level that B is always executed when M is "ready". I could normally do something like this by adding a phantom parameter to M, to track it's state and allow B to only be called with M "ready". This is fine, and I could use an indexed monad to not have to pass around M explicitly. However I cannot figure out how to enforce something like this when dealing with multiple threads, with more than one potentially executing A and/or B (changing the state or requiring the state to be changed). ======= Georgi
participants (3)
-
Georgi Lyubenov
-
Tom Ellis
-
Viktor Dukhovni