Re:Understanding contravariance
by a1369209993 on Sunday June 24, 2018 @03:15AM
(#17385400)
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.
Re:Understanding contravariance
by tome on Sunday June 24, 2018 @12:34PM
(#17387139)
That's not the sort of variance that was discussed in the article, where an explicit mapping function is applied, not an implicit subtying relationship.
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.