adenizgelir
adenizgelir

Reputation: 3

can't implement matrices and vectors using GADTs in haskell

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

Answers (1)

bergey
bergey

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

Related Questions