My first Haskell: dice rolling
The list comprehension you use in diceCode is a bit overkill: after all, you only want to split the list of characters into two. You can use break instead.

Here I have to use fmap tail to act on the second list because break retains the value it breaks the list at (the 'd' character here). This would be a good place to handle the sort of errors that would arise if there is no 'd' in the string.

diceCode :: String -&gt; Dice
diceCode die = (read rolls, read sides) where
  (rolls, sides) = fmap tail $ break ('D' ==) $ fmap toUpper die


Your rollDice is a bit complex. Here is how I would rewrite it:


(rolls, sides) on the left hand side exposes the two components of the tuple
[1..rolls] generates a list of length rolls
mapM (const $ rollDie sides) replaces all the numbers in that list with an invocation of rollDie sides and performs the same job as sequence thus returning an Random g [Int]
sum &lt;$&gt; (or fmap sum $) goes under the Random g part and sums the elements in the [Int] value.


Putting all this together we get:

rollDice :: (RandomGen g) =&gt; Dice -&gt; Rand g Int
rollDice (rolls, sides) = sum &lt;$&gt; mapM (const $ rollDie sides) [1..rolls]


The rest of the code is quite idiomatic. One thing I was a bit concerned about is the fact that a Dice is represented as a pair of Ints: to understand which is which, you need to read the code manipulating them and if you make a mistake the compiler won't warn you: they have the same type! It's quite annoying. One thing you could do is use a record type instead in order to name the two fields:

data Dice' = Dice' { rolls :: Int
                   , sides :: Int }


This way you can access them by their names, build the Dice' using the named syntax, etc.