Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why I can´t pattern match in Haskell Typeclass?

I´m trying to roll an algebraic data type Die in Haskell defined with the following definition

data Die = Die6 | Die4 | Die20 | Die100

I have defined the following typeclass

class Roll a where
  roll :: (RandomGen g) => a -> Int -> g -> ([Int], g)
  rollR :: (RandomGen g) => a -> Int -> Int -> Int -> g -> ([Int], g)

instance Roll Die where
  roll Die6 times = generateIntRandomsArray 1 6 times
  rollR Die6  times first last = generateIntRandomsArray first last times
  {--
  roll Die4 times = generateIntRandomsArray 1 4 times (mkStdGen 4)
  rollR Die4 times first last = generateIntRandomsArray first last times (mkStdGen 4)
  --}

In case I include just rollDie6 and rollRDie6 in the instance, everything is fine, but when I try to include Die4, Iḿ getting the following error :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

DieRoller.hs:16:3: error:
    Conflicting definitions for ‘roll’
    Bound at: DieRoller.hs:16:3-6
              DieRoller.hs:18:3-6
   |
16 |   roll Die6 times = generateIntRandomsArray 1 6 times
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

DieRoller.hs:17:3: error:
    Conflicting definitions for ‘rollR’
    Bound at: DieRoller.hs:17:3-7
              DieRoller.hs:19:3-7
   |
17 |   rollR Die6  times first last = generateIntRandomsArray first last times
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

I don´t get the point . I want to define different behaviour depending the Die has 4 or 6 sides, but looks like I’m missing something . Can you help me ? Thanks . Just to give you a little bit more of info , generateIntRandomsArray has the following definition :

generateIntRandomsArray :: (Eq a, Random a, Num a, RandomGen g) => a -> a -> a -> g -> ([a], g)
generateIntRandomsArray start end = generate
    where generate 0 generator = ([], generator)
          generate numberElements generator =
              let (value, newGenerator) = randomR (start,end) generator
                  (restOfList, finalGenerator) = generate (numberElements-1) newGenerator
              in  (value:restOfList, finalGenerator)

>Solution :

You define a function in one "block", not in multiple blocks, so:

instance Roll Die where
  roll Die4 = generateIntRandomsArray 1 4
  roll Die6 = generateIntRandomsArray 1 6
  
  rollR Die4 times first last = generateIntRandomsArray first last times
  rollR Die6  times first last = generateIntRandomsArray first last times

otherwise you are defining multiple functions with the same name, wich clashes of course.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading