Yesterday morning I decided to stop procrastinating and start learning me some Haskell.
So far I've made this, which is a simple cli 'dice rolling' utility that can be used like:
$ ./dice 3d20 You rolled: 17
The code looks like this:
import Data.List.Split import Data.Char import Control.Monad import Control.Monad.Random import System.Environment type Dice = (Int, Int) diceCode :: String -> Dice diceCode die = (parts!!0, parts!!1) where parts = [read x :: Int | x <- take 2 (splitOn "D" (map toUpper die))] rollDie :: (RandomGen g) => Int -> Rand g Int rollDie sides = getRandomR (1, sides) rollDice :: (RandomGen g) => Dice -> Rand g Int rollDice dice = liftM sum (sequence(replicate rolls (rollDie sides))) where rolls = fst dice sides = snd dice main = do args <- getArgs roll <- evalRandIO (rollDice (diceCode (args!!0))) putStrLn ("You rolled: " ++ show roll)
I was able to get the
diceCode 'parsing' function by myself without too much trouble.
rollDie function is almost straight from an example in the
Control.Monad.Random docs, which helped a lot.
I struggled for quite a while to find a recipe for summing the rolls in
rollDice... it seemed to me I ought to use
msum but I couldn't find a way to make it work.
liftM sum seems to do exactly what I wanted though.
I also found the use of tuples quite cumbersome. In Python I could just do:
rolls, sides = dice
but I seem to have to use the horribly-named
snd functions to access the members in Haskell (?)
I guess the next part of my adventure is to try and incorporate this into a larger program, eg a simple game. It seems like the monadically-wrapped random int values are going to force the rest of the code to be 'monad-aware' (i.e. lots of use of
liftM) and I wonder if there is a way to avoid this?