0

I have made a type class and made list an instance of type class but I am getting an error which I do not understand

class MyType a where
listsum:: a->a->Double

instance (Num a)=>MyType [a] where
    listsum x y = sum $ zipWith (-) x y 

listsum returns a single value but this is the error I get:

 Could not deduce (a ~ Double)
from the context (Num a)
  bound by the instance declaration at b2.hs:4:10-28
  `a' is a rigid type variable bound by
      the instance declaration at b2.hs:4:10
In the expression: sum $ zipWith (-) x y
In an equation for `listsum': listsum x y = sum $ zipWith (-) x y
In the instance declaration for `MyType [a]'
Failed, modules loaded: none.

How do I solve this?

2 Answers 2

2

Let's write down some annotations.

sum     :: (Num a, Foldable t) => t a -> a
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
(-)     :: Num a => a -> a -> a

Let's derive the type of \ x y -> sum $ zipWith (-) x y.

-- 1. Let's substitute (-) to zipWith:

zipWith (-) :: Num a => [a] -> [a] -> [a]

-- 2. Let's substitute `(zipWith (-))` to `sum`. We can't
-- write it point free like in `zipWith (-)` case. So we add
-- two extra params:

(\ x y -> sum $ zipWith (-) x y) :: Num a => [a] -> [a] -> a

The type of listsum for [a] is:

listsum :: (Num a) => [a] -> [a] -> Double

It takes two lists of something of (Num a => a) and returns Double. But (\ x y -> sum $ zipWith (-) x y) returns any (Num a => a). The compiler cannot be sure that this (Num a => a) will always be Double. That's why you get the error:

Could not deduce (a ~ Double) from the context (Num a)

@sclv gave you two options to solve it. Another one is to change the MyType class to

class MyType a where
    listsum:: [a] -> [a] -> a

so that the listsum and (\ x y -> sum $ zipWith (-) x y) has the same type.

It also gives you an opportunity to parametrize listsum by a type of elements of list.

Sign up to request clarification or add additional context in comments.

Comments

1

You can modify listsum:: a -> a -> Double to be listsum :: [a] -> [a] -> a and declare your instance over a rather than [a] Or you can modify your instance from instance (Num a) => MyType [a] to instance MyType [Double].

You can see the error by just taking the type of the expression \x y -> sum $ zipWith (-) x y. You will see that it is Num a => [a] -> [a] -> a and not Num a => [a] -> [a] -> Double as your class currently requires.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.