I am new to Haskell, so hopefully this is not a dumb question. I have this data type:
data N = I Int | D Double deriving (Show, Eq)
I am trying to write a function with the signature (Num a) => (a -> a -> a) -> N -> N -> N , which applies this function to numbers inside N and returns N with the result. If N both D s, it should just apply the function and return a D ; if one of I and the other is D , it must convert Int to I in Double , apply the function to two Double s and return a D ; and if both of them are I s, he must apply the function and return I Here is the (broken) code that I still have:
widen :: N -> N -> (N, N) widen (I i) d@ (D _) = (D (fromIntegral i), d) widen d@ (D _) i@ (I _) = widen id widen xy = (x, y) numOp :: (Num a) => (a -> a -> a) -> N -> N -> N numOp op xy = case widen xy of (D x', D y') -> D $ x' `op` y' (I x', I y') -> I $ x' `op` y'
I get an error on both numOp lines. The first one is:
Could not deduce (a ~ Double) from the context (Num a) bound by the type signature for numOp :: Num a => (a -> a -> a) -> N -> N -> N at <line num> In the second argument of `($)', namely x' `op` y' In the expression: D $ x' `op` y' In a case alternative: (D x', D y') -> D $ x' `op` y'
And the second:
Couldn't match type `Double' with `Int' Expected type: Int Actual type: a In the second argument of `($), namely x' `op` y' In the expression: I $ x' `op` y' In a case alternative: (I x', I y') -> I $ x' `op` y'
I am sure I understand what both errors mean; I think the first one says that the information in my type signature is not enough for GHC to suggest that op returns a Double , which is required by the constructor of the D value, and the second one says that since the first line implies that a Double , this line cannot use a value of type a as if it were Int . I donβt even know where to start looking for the right way to do this.
If this helps, the reason I'm trying to get it to work is that I follow. Write a textbook for yourself ; all the examples in the tutorial (especially in the Evaluation section) concern only integers, but as an exercise I would like to add the ability to support both integral and floating point numbers, so for example, (+ 1 2.5 2.5) returns 6.0 and (+ 1 2 3) returns 6 . If I think about it in the wrong way or there is an easier way to achieve it, I would like to hear suggestions.