I can't answer the whole question, but for the list version, I got this to work:
main = [1, 2, 3] `arplus` [4, 5, 6] class Narry a where arplus :: a → a → a instance (Num a) ⇒ Narry [a] where arplus = zipWith (+)
I also tried turning (Num a) => [a] into a Num instance that had good results.
instance (Num a) ⇒ Num [a] where (+) = zipWith (+) (*) = zipWith (*) (-) = zipWith (-) negate = map negate abs = map abs signum = map signum fromInteger = repeat∘fromInteger
You can try it just like
main = do print $ [1, 2, 3] * 3 -- [3, 6, 9] print $ 3 * [1, 2, 3] -- [3, 6, 9] print $ 3 - [2, 4, 6] -- [-1, 1, 3] print $ [2, 4, 6] + 7 -- [9, 11, 13] print $ abs [-2, 4, -3] -- [2, 4, 3] print $ [1, 2, 3] + [4.3, 5.5, 6.7] -- [5.3, 7.5, 9.7] print $ [1, 2, 3] * [3, 4, 5] -- [3, 8, 15]
Of course, if you want to do double arithmetic with lists, then you have to write definitions for a few more things. I am not sure what might affect my definition here, although I suspect that this is not much more than what I have demonstrated.
Also, this is not the only way to make Nums lists an instance of Num; probably a better choice than zipWith for (*).
[EDIT] Creating Fractional instance lists is trivially easy and adds even more convenience.
instance (Fractional a) => Fractional [a] where recip = map recip fromRational = repeat . fromRational
This makes it possible to use a list with fractional interactions and automatically divides the work!
ghci> [3, 6, 9] / 3 [1.0,2.0,3.0] ghci> 9 / [1, 2, 3] [9.0,4.5,3.0] ghci> 1.2 + [0, 1, 2] [1.2,2.2,3.2]
With great power comes great responsibility; use them only if you need them. If you don’t need it, then it’s nice that the compiler yells at you when you try to call + on a number and a list.