Reputation: 23135
The following code compiles on GHC-7.8.3, but I can't figure out how to write a explicit type signature for f
:
import qualified Data.Vector.Generic.Mutable
import Data.Vector.Generic (freeze, thaw, Mutable, Vector)
import Control.Monad.Primitive (PrimState, PrimMonad)
import Control.Monad.ST (runST, ST)
f v = Data.Vector.Generic.Mutable.read v 0 >>=
Data.Vector.Generic.Mutable.write v 0 >>
return v
g :: Vector v a => v a -> v a
g v = runST $ (thaw v) >>= f >>= freeze
main = return ()
f
here is just a function that does some work on a mutable vector and returns a mutable vector. I've done a dummy read
and write
just to force the type to be a vector.
So how can I write a type signature for f
?
Note: I've significantly edited and the question to clarify and simplify it.
Upvotes: 3
Views: 140
Reputation: 14623
That type for f
doesn't really make sense, precisely because type families are non injective (which is exactly what it tells you). You are saying f
takes a Mutable v (PrimState m) a
, but that cannot determine what v
actually is - this is the meaning of non-injective. Then, the output must depend on v
. But again you don't know what v
is.
In this case the solution is obvious: give f
the type Monad m => a -> m a
. But in general, you have to pass the type v
to the function somehow. Typically you would write
f :: (PrimMonad m, Vector v a)
=> proxy v -> Mutable v (PrimState m) a -> m (Mutable v (PrimState m) a)
f _ = return
The inferred type of
f v = read v 0 >>=
write v 0 >>
return v
is
(MVector v a, PrimMonad m) => v (PrimState m) a -> m (v (PrimState m) a)
The argument to the function isn't a type family application. This is precisely the explicit type you should give it. The type v
is known. If you were to try to give it the type
(PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> m (Mutable v (PrimState m) a)
like before, you get the exact same error.
Upvotes: 2