News for hackers. Stuff that matters.
Re:Understanding contravariance by tome on Saturday June 23, 2018 @01:39AM (#17379723)
A mutable array in Haskell is most certainly covariant so you may have to rethink your counterexample.
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.