Haskell's Data.Array.IO IOArrays (which I assume you're talking about) are
not covariant; they are
invariant, with a very nice type inference system to paper over this in most cases.
{-# OPTIONS_GHC -W -XRankNTypes -XImpredicativeTypes -XFlexibleContexts #-}
import Data.Array.IO
type Subtype = (forall a . a->Int)
type Suptype = (Int -> Int)
esub = (\_ -> 0) :: Subtype
esup = (\x -> x+1) :: Suptype
wantsub = (\f -> f 'a') :: Subtype -> Int
wantsup = (\f -> f 0) :: Suptype -> Int
writeArraySup :: IOArray Int Suptype -> IO ()
writeArraySup a = writeArray a 1 esup
main = do asub <- newArray (1,1) esub
writeArraySup asub
a1sub <- readArray asub 1
print $ wantsub a1sub
In the above code, asub can be
either (ie, not both) `IOArray Int Suptype` (in which case wantsub will fail to typecheck)
or `IOArray Int Subtype`, in which case writeArraySup will fail to typecheck, because A'Sub isn't actually a subtype of A'Sup, because IOArray Int isn't actually covariant. You can see, I hope, that if they
were covariant, and writeArraySup
did typecheck, then we would end up passing 'a' (a Char) into (+) (expects Int) in violation of type safety.
If you meant some other mutable array type, then the same reasoning applies, but I can't be arsed to work out another concise example.