In my project I have a few data types that look like this
data StructureA = StructureA [Int] Bool Int
data StructureB = StructureB [String] String
My goal is to map functions over arrays contained inside instances of such datatypes
inst = StructureA [1,1,1] True 0
fmap (+1) inst -- [2,2,2]
My initial solution solution looks like this
instance Functor StructureA where
    fmap (StructureA arr _ _) = fmap arr
However, I get kind mismatch error.
Question is how I can declare a function that can be polymorphically applied over such data structures?
You can only declare a Functor instance over a parameterized type (* -> * to be precise): a type that still needs an extra (and exactly one) type parameter.
So first we will need to introduce a type parameter. Even if you never plan to use something else than Ints, we can easily abstract that away with:
data Structure a = Structure [a] Bool IntWe can for example declare the StructureA as a type synomym:
type StructureA = Structure IntNow we can make it a Functor instance, by writing:
instance Functor Structure where
    fmap f (Structure as b c) = ...Note that we here did not write (Structure a), but Structure, since - like we already said - fmap has the freedom to change the type over which the collection works: the f function can have for example type Int -> Char to convert a Structure Int to a Structure Char.
Now we still need to implement fmap. fmap has type fmap :: Functor f => (a -> b) -> f a -> f b so that means it takes a function, and in this case a Structure a, and constructs a Structure b. Based on your question (and the design decisions we have made), the only part we can map is the first parameter, so we construct a new Structure, where the second parameter is the result of an fmap f, but then over the second parameter, so:
instance Functor Structure where
    fmap f (Structure as b c) = Structure (fmap f as) b cIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With