Since you allow any function to be applied to the list of coefficients, your data type only really serves two purposes.
- You get extra type safety, since a
Poly [a] is distinct from [a].
- You can define different instances.
If you don't need either of these, you might as well use a type alias.
type Poly a = [a]
Now you can apply any list function on it directly.
If, on the other hand, you want a distinct type, you might find the newtype package useful. For example, given this instance.
instance Newtype (Poly a) [a] where
pack = Poly
unpack (Poly x) = x
You can now write things like
foo :: Poly a -> Poly a
foo = over Poly (take 3)
although this might be overkill if your myMap is sufficient for your purposes.
All this aside, I think that exposing the representation of your data type in such a way might not be a good idea in the first place, as it can leave the rest of your code intimately dependent on this representation.
This makes it harder to change to a different representation at a later time. For example, you might want to change to a sparse representation like
data Poly a = Poly [(a, Int)]
where the Int is the power of the term. I suggest thinking about what operations you want to expose, and limiting yourself to those. For example, it might make sense to have a Functor instance that works on a per-element basis.
instance Functor Poly where
fmap f (Poly x) = Poly $ map f x
Now, the change to the sparse representation leaves client code unchanged. Only the instance (and the handful of other functions that depend on the representation) will have to change.
instance Functor Poly where
fmap f (Poly x) = Poly $ map (first f) x
fmap (take 3) polynomialto do? It doesn't make sense to me at all. —polynomialis simply apolynomial :: Poly CoeffTypepolynomial = Poly [a₁, a₂ ..]? - leftaroundaboutmap" but rathercoeffsTransformor something like that. - leftaroundabout