haskelltypeclass

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 :

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.