As always, statements like "I'm trying (with no success) this" are not quite as useful as you would like: it's good that you included your code, but if you are getting an error message from the compiler, tell us what it is! They're very instructive, and are printed for a reason.
I just tried what you wrote, and this is in fact the error message you are (probably) getting:
*Multiplication> mul 1 [2]
Non type-variable argument
in the constraint: Multipliable ta [t] tc
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall ta tc t. (Num ta, Num t, Multipliable ta [t] tc) => tc
Now, you could try just turning on FlexibleContexts, but that doesn't seem to solve the problem. But, as is often the case when the compiler is telling you it's having trouble inferring types, you should try adding some explicit types and see if that helps:
*Multiplication> mul (1::Double) [2 :: Double]
[2.0]
Basically, the compiler can't be sure which overload of mul
you want: 1
and 2
are polymorphic and could be any numeric type, and while there is only one suitable overload for mul
now, the compiler doesn't make such an inference unless it can prove no other overload could ever exist in this context. Fully specifying the argument types is enough to resolve the problem.
An alternative approach to this particular problem is to use a typeclass for each argument, to convert it into the canonical type [Double]
, rather than a typeclass for the arguments as a whole. This is a more specific solution than general ad hoc polymorphism, and not all problems will fit, but for something like treating a single number like a list of numbers it should be fine:
module Multiplication where
import Control.Monad (liftM2)
class AsDoubles a where
doubles :: a -> [Double]
instance AsDoubles Double where
doubles = return
instance AsDoubles [Double] where
doubles = id
mult :: (AsDoubles a, AsDoubles b) => a -> b -> [Double]
mult x y = liftM2 (*) (doubles x) (doubles y)
*Multiplication> mult [(1 :: Double)..5] [(1 :: Double)..3]
[1.0,2.0,3.0, -- whitespace added for readability
2.0,4.0,6.0,
3.0,6.0,9.0,
4.0,8.0,12.0,
5.0,10.0,15.0]