From Ninety-Nine Haskell Problems:
Question 23: Extract a given number of randomly selected elements from a list.
This is a partial solution. For simplicity, this code just selects one element from a list.
import System.Random (randomRIO)
randItem :: [a] -> IO a
randItem xs = do
i <- randomRIO (0,length xs - 1)
return $ xs !! i
so randItem [1..10] would return an IO Int that corresponds to (but does not equal) some Int from 1 through 10.
So far, so good. But what kind of tests can I write for my randItem function? What relationship--if any--can I confirm between the input and output?
I can use the same logic as the above function to produce m Bool, but I cannot figure out how to test for m Bool. Thank you.
There's a couple of things you can do. If you're using QuickCheck, you could write the following properties:
The length of the returned list should be equal to the input length.
All elements in the returned list should be elements of the list of candidates.
Apart from that, the beauty of Haskell's Random library is that (as most other Haskell code) it's deterministic. If, instead of basing your implementation on randomRIO, you could base it on randomR or randomRs. This would enable you to pass some known RandomGen values to some deterministic unit test cases (not QuickCheck). These could serve as regression tests.
I've now published an article about the above approach, complete with source code.
Related
This is a very simple linear-congruent pseudo-random number generator. It works fine when I seed it, but I want to make it so that it self-seeds with every produced number. Problem is that I don't know how to do that in Haskell where the notion of variables does not exist. I can feed the produced number recursively, but then my result would be a list of integers instead of a single number.
linCongGen :: Int -> Int
linCongGen seed = ((2*seed) + 3) `mod` 100
I'll summarize the comments a bit more meaningfully. The simplest solution is, like you observed, an infinite list of the sequence of generated elements. Then, every time you want to get a new number, pop off the head of that list.
linCongGen :: Integral a => a -> [a]
linCongGen = iterate $ \x -> ((2*x) + 3) `mod` 100
That said, here is a solution (which I do not agree with), but which does what I think you want. For mutable state, we usually use IORef, which is sort of like a reference or pointer. Here is the code. Please read the disclaimer afterwards though.
import Data.IORef
import System.IO.Unsafe
seed :: IORef Int
seed = unsafePerformIO $ newIORef 71
linCongGen :: IO Int
linCongGen = do previous <- readIORef seed
modifyIORef' seed $ \x -> ((2*x) + 3) `mod` 100
return previous
And here is a sample usage printing out the first hundred numbers generated: main = replicateM_ 100 $ getRandom >>= print (you'll need to have Control.Monad imported too for replicateM_).
DISCLAIMER
This is a bit of a hacky approach described here. As the link says "Maybe the need for global mutable state is a symptom of bad design." The link also has a good description of a more intelligent workaround. Making an IORef is an inherently IO operation, and we really shouldn't be using unsafePerformIO on it. If you find yourself fighting Haskell in this way, it's because Haskell was designed to get in your way when you are doing things you shouldn't.
That said, I find comfort in knowing that this approach is also the one using in System.Random (the standard random number module) to define the initial seed (check out the source).
I'm writing this after a good while of frustrating research, and I'm hoping someone here can enlighten me about the topic.
I want to generate a simple random number in a haskell function, but alas, this seems impossible to do without all sorts of non-trivial elements, such as Monads, asignation in "do", creating generators, etc.
Ideally I was looking for an equivalent of C's "rand()". But after much searching I'm pretty convinced there is no such thing, because of how the language is designed. (If there is, please someone enlighten me). As that doesn't seem feasible, I'd like to find a way to get a random number for my particular problem, and a general explanation on how it works to get a random number.
prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = frequency [
(1, return ([],[])),
(2, do {
xs1 <- orderedListEj13 ;
xs2 <- orderedListEj13 ;
return (xs1,xs2)
}),
(2, do {
xs2 <- orderedListEj13 ;
return ((take RANDOMNUMBERHERE xs2),xs2)
})
]
I'm trying to get to grips with QuickCheck but my inability to use random numbers is making it hard. I've tried something like this (by putting an drawInt 0 (length xs2) instead of RANDOMNUMBERHERE)but I get stuck with the fact that take requires an Int and that method leaves me with a IO Int, which seems impossible to transform to an Int according to this.
As haskell is a pure functional programming language, functions are referentially transparent which means essentially that only a function's arguments determine its result. If you were able to pull a random number out of the air, you can imagine how that would cause problems.
I suppose you need something like this:
prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = do
randn <- choose (1,999) -- number in range 1-999
frequency [
(1, return ([],[])),
(2, do {
xs1 <- orderedListEj13 ;
xs2 <- orderedListEj13 ;
return (xs1,xs2)
}),
(2, do {
xs2 <- orderedListEj13 ;
return ((take randn xs2),xs2)
})
]
In general in haskell you approach random number generation by either pulling some randomness from the IO monad, or by maintaining a PRNG that is initialized with some integer seed hard-coded, or pulled from IO (gspr's comment is excellent).
Reading about how pseudo random number generators work might help you understand System.Random, and this might help as well (scroll down to section on randomness).
You're right in that nondeterministic random (by which I mean "pseudo-random") number generation is impossible without trickery. Functions in Haskell are pure which means that the same input will always produce the same output.
The good news is that you don't seem to need a nondeterministic PRNG. In fact, it would be better if your QuickCheck test used the same sequence of "random" numbers each time, to make your tests fully reproducible.
You can do this with the mkStdGen function from System.Random. Adapted from the Haskell wiki:
import System.Random
import Data.List
randomInts :: Int -> [Int]
randomInts n = take n $ unfoldr (Just . random) (mkStdGen 4)
Here, 4 is the seed that you may want to choose by a fair dice roll.
The standard library provides a monad for random-number generation. The monadic stuff is not that hard to learn, but if you want to avoid it, find a pseudo-random function next that takes an Int to an Int in a pseudorandom way, and then just create and pass an infinite list of random numbers:
next :: Int -> Int
randoms :: [Int]
randoms = iterate next 73
You can then pass this list of random numbers wherever you need it.
Here's a linear congruential next from Wikipedia:
next n = (1103515245 * n + 12345) `mod` 1073741824
And here are the first 20 pseudorandom numbers following 73:
Prelude> take 20 $ iterate next 73
[73,25988430,339353199,182384508,910120965,1051209818,737424011,14815080,325218177,1034483750,267480167,394050068,4555453,647786674,916350979,980771712,491556281,584902142,110461279,160249772]
I'm trying to store randomly generated dice values in some data structure, but don't know how exactly to do it in Haskell. I have so far, only been able to generate random ints, but I want to be able to compare them to the corresponding color values and store the colors instead (can't really conceive what the function would look like). Here is the code I have --
module Main where
import System.IO
import System.Random
import Data.List
diceColor = [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
diceRoll = []
rand :: Int -> [Int] -> IO ()
rand n rlst = do
num <- randomRIO (1::Int, 6)
if n == 0
then printList rlst -- here is where I need to do something to store the values
else rand (n-1) (num:rlst)
printList x = putStrLn (show (sort x))
--matchColor x = doSomething()
main :: IO ()
main = do
--hSetBuffering stdin LineBuffering
putStrLn "roll, keep, score?"
cmd <- getLine
doYahtzee cmd
--rand (read cmd) []
doYahtzee :: String -> IO ()
doYahtzee cmd = do
if cmd == "roll"
then do rand 5 []
else putStrLn "Whatever"
After this, I want to be able to give the user the ability to keep identical dices (as in accumulate points for it) and give them a choice to re-roll the left over dices - I'm thinking this can done by traversing the data structure (with the dice values) and counting the repeating dices as points and storing them in yet another data structure. If the user chooses to re-roll he must be able to call random again and replace values in the original data structure.
I'm coming from an OOP background and Haskell is new territory for me. Help is much appreciated.
So, several questions, lets take them one by one :
First : How to generate something else than integers with the functions from System.Random (which is a slow generator, but for your application, performance isn't vital).
There is several approaches, with your list, you would have to write a function intToColor :
intToColor :: Int -> String
intToColor n = head . filter (\p -> snd p == n) $ [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
Not really nice. Though you could do better if you wrote the pair in the (key, value) order instead since there's a little bit of support for "association list" in Data.List with the lookup function :
intToColor n = fromJust . lookup n $ [(1,"Black"),(2,"Green"),(3,"Purple"),(4,"Red"),(5,"White"),(6,"Yellow")]
Or of course you could just forget this business of Int key from 1 to 6 in a list since lists are already indexed by Int :
intToColor n = ["Black","Green","Purple","Red","White","Yellow"] !! n
(note that this function is a bit different since intToColor 0 is "Black" now rather than intToColor 1, but this is not really important given your objective, if it really shock you, you can write "!! (n-1)" instead)
But since your colors are not really Strings and more like symbols, you should probably create a Color type :
data Color = Black | Green | Purple | Red | White | Yellow deriving (Eq, Ord, Show, Read, Enum)
So now Black is a value of type Color, you can use it anywhere in your program (and GHC will protest if you write Blak) and thanks to the magic of automatic derivation, you can compare Color values, or show them, or use toEnum to convert an Int into a Color !
So now you can write :
randColorIO :: IO Color
randColorIO = do
n <- randomRIO (0,5)
return (toEnum n)
Second, you want to store dice values (colors) in a data structure and give the option to keep identical throws. So first you should stock the results of several throws, given the maximum number of simultaneous throws (5) and the complexity of your data, a simple list is plenty and given the number of functions to handle lists in Haskell, it is the good choice.
So you want to throws several dices :
nThrows :: Int -> IO [Color]
nThrows 0 = return []
nThrows n = do
c <- randColorIO
rest <- nThrows (n-1)
return (c : rest)
That's a good first approach, that's what you do, more or less, except you use if instead of pattern matching and you have an explicit accumulator argument (were you going for a tail recursion ?), not really better except for strict accumulator (Int rather than lists).
Of course, Haskell promotes higher-order functions rather than direct recursion, so let's see the combinators, searching "Int -> IO a -> IO [a]" with Hoogle gives you :
replicateM :: Monad m => Int -> m a -> m [a]
Which does exactly what you want :
nThrows n = replicateM n randColorIO
(I'm not sure I would even write this as a function since I find the explicit expression clearer and almost as short)
Once you have the results of the throws, you should check which are identical, I propose you look at sort, group, map and length to achieve this objective (transforming your list of results in a list of list of identical results, not the most efficient of data structure but at this scale, the most appropriate choice). Then keeping the colors you got several time is just a matter of using filter.
Then you should write some more functions to handle interaction and scoring :
type Score = Int
yahtzee :: IO Score
yahtzeeStep :: Int -> [[Color]] -> IO [[Color]] -- recursive
scoring :: [[Color]] -> Score
So I recommend to keep and transmit a [[Color]] to keeps track of what was put aside. This should be enough for your needs.
You are basically asking two different questions here. The first question can be answered with a function like getColor n = fst . head $ filter (\x -> snd x == n) diceColor.
Your second question, however, is much more interesting. You can't replace elements. You need a function that can call itself recursively, and this function will be driving your game. It needs to accept as parameters the current score and the list of kept dice. On entry the score will be zero and the kept dice list will be empty. It will then roll as many dice as needed to fill the list (I'm not familiar with the rules of Yahtzee), output it to the user, and ask for choice. If the user chooses to end the game, the function returns the score. If he chooses to keep some dice, the function calls itself with the current score and the list of kept dice. So, to sum it up, playGame :: Score -> [Dice] -> IO Score.
Disclaimer: I am, too, very much a beginner in Haskell.
at first thought:
rand :: Int -> IO [Int]
rand n = mapM id (take n (repeat (randomRIO (1::Int, 6))))
although the haskellers could remove the parens
Does anyone know exactly how to define a generator in Haskell using QuickCheck such that chosen elements are picked only ONCE?
I've gotten as far as realizing that I might need a "Gen (Maybe Positive)" generator, but of course that will generate number with repetition. I want it so that the numbers chosen are picked without repetition. In the instance when a number is returned I want Just returned and in the instance where the randoms are all exhausted I want Gen Nothing returned.
Thanks,
Mark
You can't. Look at the definition of Gen. There's no way for it to carry any state about what has been picked so far. Given the same random generator and size limit it must always generate the same result. You can however write a Eq a => Gen [a] that generates a list of values with no repetitions. A simple (but somewhat naive) one would be something like this.
uniques :: Eq a => Gen a -> Gen [a]
uniques gen = fmap nub $ listOf gen
QuickCheck is generally for randomized testing, not exhaustive testing. There are a few great libraries that do handle exhaustive testing -- look at smallcheck and lazysmallcheck.
You can use permutations (in module Data.List) for this.
Here is the function signature for permutations:
permutations :: [a] -> [[a]]
As you can see, it returns a list of lists. Here is a little example (using GHCi 7.0.4):
> permutations [1..3]
[[1,2,3],[2,1,3],[3,2,1],[2,3,1],[3,1,2],[1,3,2]]
So you could do something like:
prop_unique_elements = forAll (elements (permutations [1..3])) $ \x -> foo == bar
I haven't tested that so it will need some massaging, but I hope it conveys the point clearly. Good luck.
I have a file containing many prime numbers.
I'd like to write a module with the following functions:
module Primes as
( init,
primes,
is_prime)
where ...
where init should read the file and initialize the primes which should be a list and also is_prime.
My problem is, how should I write it? Isn't there a way to "hide" the IO monad?
More generally I believe I think like an OO programmer. What is the good functional way to handle this?
The way to 'hide' the IO monad is to write isPrime (and any other functions that use the list of prime numbers) as a pure function, and only introduce IO as late as you possibly need. The fact that you are using a list of pregenerated prime numbers and reading them from a file is just an implementation detail that is irrelevant to general functions dealing with prime numbers.
Here's a simple implementation of a pure isPrime that takes an integer to test and a list of prime numbers. Notice that it doesn't care where the list of primes came from, just that it's a list of integers.
isPrime :: Integer -> [Integer] -> Bool
isPrime n ps = n `elem` ps
Now let's introduce a function that will read the prime numbers from disk. Its return type must be in the IO monad because, well, we're performing I/O.
readPrimesFromFile :: String -> IO [Integer]
readPrimesFromFile filename = ...
Now we can use this function in combination with our isPrime function. Once we start using readPrimesFromFile we are forever 'trapped' in the IO monad.
main :: IO ()
main = do
primeList <- readPrimesFromFile "primes.txt"
let result = isPrime 123 primeList
print result
Why exactly do you start with a file of primes? The IO time to read the file is probably slower than just generating the primes from scratch.
See Data.Numbers.Primes for (afaik) the most efficient way to generate the list of all prime numbers.