Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell cannot match type

Tags:

haskell

I'm still a beginner with Haskell and I've this piece of code, but ghc doesn't compile and gives me an error

This is the code:

data QT a = C a | Q (QT a) (QT a) (QT a) (QT a) deriving (Show)

moltiply :: QT a -> Int -> QT a
moltiply (C a) x = (C (a * x))
moltiply (Q a b c d) x = Q (moltiply a x) (moltiply b x) (moltiply c x) (moltiply d x)

And this is the error I get:

Couldn't match expected type ‘a’ with actual type ‘Int’
      ‘a’ is a rigid type variable bound by
          the type signature for multiply :: QT a -> Int -> QT a
          at file.hs:12:15
    Relevant bindings include
      a :: a (bound at file.hs:13:15)
      multiply :: QT a -> Int -> QT a
        (bound at file.hs:13:1)
    In the second argument of ‘(*)’, namely ‘x’
    In the first argument of ‘C’, namely ‘(a * x)’
like image 221
zeb Avatar asked Dec 24 '22 12:12

zeb


2 Answers

When you write

moltiply :: QT a -> Int -> QT a

you're telling GHC that this function will work with any type a inside your QT type, but then you write

moltiply (C a) x = (C (a * x))

and try to multiply the value a which can be of any type with an Int. This does not seem right does it?

You can fix this in two ways:

  1. Ask GHCi what the most general type of moltiply is by removing the type signature and loading the file in GHCi:

    λ> :t moltiply
    moltiply :: Num a => QT a -> a -> QT a
    

    Then you can add this type signature to your source file (good for documentation) or leave the function without a type signature.

  2. Stick to Int by saying that moltiply requires QT to contain an Int:

    moltiply :: QT Int -> Int -> QT Int
    
like image 101
adamse Avatar answered Jan 02 '23 22:01

adamse


The only thing you can multiply by an Int using * is another Int. You need to either restrict your type signature to

moltiply :: QT Int -> Int -> QT Int

or generalize it to

moltiply :: Num a => QT a -> a -> QT a

or change the implementation to something like

moltiply :: (Num a, Integral b) => QT a -> b -> QT a
moltiply (C a) x = (C (a * fromIntegral x))
moltiply (Q a b c d) x = Q (moltiply a x) (moltiply b x) (moltiply c x) (moltiply d x)
like image 35
dfeuer Avatar answered Jan 02 '23 22:01

dfeuer