The following code will be not compile:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV
bad :: V.Vector Int
bad = id . V.create $ do
v <- MV.new 1
MV.set v 0
pure v
• Couldn't match type ‘m0 (MV.MVector (Control.Monad.Primitive.PrimState m0) a0)’ with ‘forall s. GHC.ST.ST s (MV.MVector s Int)’ Expected type: m0 (MV.MVector (Control.Monad.Primitive.PrimState m0) a0) -> V.Vector Int Actual type: (forall s. GHC.ST.ST s (MV.MVector s Int)) -> V.Vector Int • In the second argument of ‘(.)’, namely ‘V.create’ In the expression: id . V.create In the expression: id . V.create $ do { v <- MV.new 1; MV.set v 0; pure v }
But next will be:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV
good :: V.Vector Int
good = id $ V.create $ do
v <- MV.new 1
MV.set v 0
pure v
stack resolver is lts-9.12
So, why it does and how to fix if I prefer to compose by (.)?
You've hit the fact that GHC can't do impredicative polymorphism. V.create has the higher rank type forall a. Unbox a => (forall s. ST s (MVector s a)) -> Vector a, and when you try to apply it to (id .) :: (x -> y) -> (x -> y) you end up needing to instantiate x = forall s. ST s (MVector s a), which explodes. It's not that there's anything really wrong with the required instantiation; it's just that GHC cannot deal with it. There used to be an extension, ImpredicativePolymorphism, that tried to give limited support, but as of GHC 8 it's completely broken and deprecated. The reason ($) still works is because it's actually hardwired into GHC so that it can avoid the issue, which is why if you tried to define
f $$ x = f x
and used it instead of ($) here it'd fail similarly to (id .).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With