In an attempt to learn how to write more generic code, I tried to write a simple Array class. The idea is to write some simple array operations only with the functions provided by the Array class and then to write different data types as instances. So I want to write different representations of arrays.
For a first attempt, an array has a number of rows and columns and a container that is foldable.
module Array where
import qualified Data.Vector as V
import Data.Foldable
class Array arr where
aRows :: arr a -> Int
aCols :: arr a -> Int
aData :: Foldable t => arr a -> t a
data VectorArray a = VectorArray
{ vRows :: !Int
, vCols :: !Int
, vData :: !(V.Vector a)}
instance Array VectorArray where
aRows = vRows
aCols = vCols
aData = vData
The last line does not compile:
• Couldn't match type ‘t’ with ‘V.Vector’
‘t’ is a rigid type variable bound by
the type signature for:
aData :: forall (t :: * -> *) a. Foldable t => VectorArray a -> t a
at src/Array.hs:19:5
Expected type: VectorArray a -> t a
Actual type: VectorArray a -> V.Vector a
• In the expression: vData
My interpretation of the error message: You (programmer) give me a V.Vector
a but I (the GHC compiler)
want a t a
where the t
must be an instance of the Foldable class.
Now, a V.Vector is an instance of Foldable. So in every function where I have to pass an instance of Foldable as an argument, I can use a value of type V.Vector. My question is: Why does GHC not "upcast" a V.Vector to a Foldable? Are there any examples, where such an upcast would be a source of problems?
PS: The real and good solution to avoid the above error is to drop the aData
function from the Array class
and to make VectorArray an instance of Foldable.