Reputation: 3
I am a beginner to Haskell. I was trying to implement Matrices and Vectors in haskell. I wanted these to support all types in Num typeclass, but not others so i tried using GADTs but i am getting errors can you explain why i am getting errors. Or can i get the same functionality without this way.
My code:
{-# LANGUAGE GADTs #-}
class LStruct s where
scale :: (Num a) => a -> s -> s
add :: s -> s -> s
data Vector a where
Vector :: (Num a) => a -> Vector [a]
data Matrix a where
Matrix :: (Num a) => a -> Matrix [a]
instance LStruct (Vector a) where
scale a (Vector xs) = Vector (map (*a) xs)
add (Vector xs) (Vector ys) = Vector (zipWith (+) xs ys)
error:
[-Wdeferred-type-errors]
• Could not deduce: a2 ~ [a1]
from the context: (a ~ [a2], Num a2)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘scale’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:12-20
‘a2’ is a rigid type variable bound by
a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘scale’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:12-20
• In the second argument of ‘map’, namely ‘xs’
In the first argument of ‘Vector’, namely ‘(map (* a) xs)’
In the expression: Vector (map (* a) xs)
• Relevant bindings include
xs :: a2
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:19)
a :: a1
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:9)
scale :: a1 -> Vector a -> Vector a
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:3)
[-Wdeferred-type-errors]
• Could not deduce: a2 ~ [c0]
from the context: (a ~ [a1], Num a1)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:8-16
or from: (a ~ [a2], Num a2)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD- TEMP.hs:21:20-28
‘a2’ is a rigid type variable bound by
a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:20-28
Expected type: [c0]
Actual type: a1
• In the second argument of ‘zipWith’, namely ‘xs’
In the first argument of ‘Vector’, namely ‘(zipWith (+) xs ys)’
In the expression: Vector (zipWith (+) xs ys)
• Relevant bindings include
ys :: a2
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:27)
Upvotes: 0
Views: 126
Reputation: 3071
I think you intended to write:
data Vector a where
Vector :: (Num a) => [a] -> Vector a
"A Vector or a's can be constructed from a list of a's"
The version in your question takes a single a
, and the errors you are getting are about GHC trying to map over that single value.
More broadly, I would recommend moving the Num
constraint from the constructor to the instances and functions that use Vector
. Code written this way seems to get better error messages from GHC, and is easier to work with. I'm not sure if there's a deep reason for this, or if it's just a question of where GHC devs have spent time.
So the instance declaration might become:
instance Num a => LStruct (Vector a) where
and the instance body can stay the same.
Upvotes: 3