Ahh I think I understand… The constructor Matrix
in the definition is hidden (so we can’t pattern match ). Instead members of Matrix
class are produced by functions like matrix
, (><)
, fromColumns
, etc. - functions whose type definitions restrict the type of matrix elements to Double
(type alias R
), Element
or Storable
type. If Matrix
could be a member of Functor
then fmap :: (a -> b) -> Matrix a -> Matrix b
would need to apply for arbitrary a
and b
. But it would only make sense for the type signature fmap :: (Storable a, Storable b) => (a -> b) -> Matrix a -> Matrix b
. Essentially this is what cmap
does, but where Container
takes the role of Functor
, and cmap
takes the role of fmap
. (Aside - it seems to me that this limited fmap
-like functionality - call it SemiFunctor
- should be totally generic, whereas the Container implementation limits what can be ‘contained’ to Element
s. Has this been done? Would it be a worthwhile addition to the Haskell ecosystem?)
I wonder - if Matrix
is to be limited to Storable
(or in practice, Element
) types, why not embed this in the data declaration using GADTs?
data Matrix t where
Matrix :: Storable t => Int -> Int -> Int -> Int -> (Vector t) -> Matrix t
-- irows icols xRow xCol xdat