How can I generate random numbers in Haskell without IO in a range? - haskell

I would like to generate random numbers in a range and the type signature to be Int -> Int. I've read multiple other posts but none of them suggested ways to return a type Int. I used System.IO.Unsafe in my code but it is not recommended to do so. Here's my code:
import System.IO.Unsafe
-- random number generator
rng :: Int -> Int
rng upper = unsafePerformIO $ randomRIO (0,upper-1)
Does anyone have any suggests on how to generate random Int in a range in Haskell?
Edit: It might be impossible to change IO Int -> Int so I converted my code to
-- random number generator
rng :: Int -> IO Int
rng upper = randomRIO (0,upper-1)
The reason why I need a rng is because I want to get random numbers within the range length of the list to get an index for an element of a list.
list !! rng (length list) but I'm getting the error Couldn't match expected type ‘Int’ with actual type ‘IO Int’ which is expected.
It's not a duplicate because 1. I want values in a range, 2. my rng does not return the same values. I'm new to Haskell and I don't know how to manipulate Monads. Any help is appreciated.

I the spirit of https://xkcd.com/221/, here's a “solution” without any IO:
rng :: Int -> Int
rng upper
| upper<=4 = upper
| otherwise = 4
So that gives you an “RFC 1149.5 compliant random number”. It's always four, unless that is outside the range.
What's the problem with this? Well, clearly it gives always the same number – and so it must be, because all Haskell functions must be functions, i.e. referentially transparent. OTOH, a random number generator is supposed to give different number each time you call it... it is thus not a function, and most other programming languages merely pretend it is a function with side-effect – because they have no proper means to express what side-effects are. Well, Haskell does have a proper means of expressing that, and it is the IO monad: you can have computations that depend on a side effect, but clearly these computations if you run them will then have that side-effect themselves.In that light, the signature Int -> IO Int does make sense for the function. (This is a function, but the result is an IO action and only executing that action gives you an Int.)
What's ugly about that is that IO Int could literally do anything in IO – it could, for instance, launch some missiles and give you back the number of casualities. More realistically, it could easily modify some file in you home directory. Whereas what you want is actually just a teeny tiny harmless side-effect, just enough to produce a new random number the next time. Usually, random number generators are anyways not really random but PRNGs, which keep a constant-size state variable that is updated in a random-looking way each time you pull a value. The next time, this state will be different and thus you get a different value, as desired. This state variable could be held in an IO-mutable location
import Data.IORef
type RandStV = Int
type RandSt = IORef RandStV
rng' :: RandSt -> Int -> IO Int
rng' rSt upper = do
x <- readIORef rSt
let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff -- https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/random_r.c;hb=glibc-2.26#l362
writeIORef rSt x'
return $ x `mod` upper
...or, you could just explicitly pass the updated state along with the result
rng'' :: Int -> RandStV -> (RandStV, Int)
rng'' upper x =
let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff
in (x', x `mod` upper)
...or it could be passed around in a dedicated state monad, which is just another way of writing the passing-on of an updated variable:
type RandStM = State RandStV
rng''' :: Int -> RandStM Int
rng''' upper = do
x <- get
let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff
put x'
return $ x `mod` upper
See the random-fu package for useful helpers on such a random monad.
One mathematical way to interpret rng''' is to say it is a function that takes an upper bound as the argument and gives you back a distribution of numbers. The distribution is always the same, but it “contains” many numbers together with the probability of them occuring. Actually generating an integer means you're sampling from the distribution.

Haskell was not built to generate random numbers without using IO.
Your example, list !! rng (length list), doesn't work because rng returns IO Int and !! expects a Int.
Here is a function that uses your rng function to get a random element from a list:
-- Will crash on empty list
randomElementFromList :: [a] -> IO a
randomElementFromList list = do
r <- rng (length list)
return $ list !! r

Related

simple function error "Variable not in scope" haskell

I have just started to code Haskell today, stuck on building function that takes an integer from user, multiply it by 3, adds one and checks if it is Even. returns the output as Boolean, true if even.
Sorry if the code is too faulty, I'm a Haskell newbie.
checkIfEven :: Int -> Bool
x <- readLn
let checkIfEven x = (even ((x*3)+1))
print checkIfEven
error:
Variable not in scope: checkIfEven :: Int -> Bool
I/O has to be handled explicitly in Haskell, as readLn is not a function; it's an IO action. It is simpler to start with a true function that takes the value to check as an argument:
checkIfEven :: Int -> Bool
checkIfEven x = even (x*3 + 1)
Note that the parentheses are not part of the call to even, but rather "grouping" the expression x * 3 + 1, as even x*3 + 1 is parsed as (even x) * 3 + 1.
Now that we have a pure function, we can apply it to a value input by the user.
program :: IO Bool
program = do
x <- readLn
return (checkIfEven (read x))
A few things to note:
<- is not an assignment operator; it's special syntax inside a do construct with "extracts" a value from (in this context) an IO action.
x will be a string, so you need to parse it to get an Int value for checkIfEven. read is a simple way to do that; we're ignoring the possibility that the user may enter a string that can not be parsed as an Int.
return doesn't return a value from a function (note we did not use it in the definition of checkIfEven. Rather, it "lifts" a value into a new IO action, has program has to be value of type IO Bool, not Bool.
Note that a do construct provides an imperative-looking way to work with IO actions. You can work directly with the underlying functions and values; in this case, we could have simply written
program = fmap (checkIfEven . read) readLn
The full explanation of how IO (and monads in general) work is beyond the scope of this question; hopefully, this will give you an idea of what to focus on as you study the topic further.

Do notation for monad in function returning a different type

Is there a way to write do notation for a monad in a function which the return type isn't of said monad?
I have a main function doing most of the logic of the code, supplemented by another function which does some calculations for it in the middle. The supplementary function might fail, which is why it is returning a Maybe value. I'm looking to use the do notation for the returned values in the main function. Giving a generic example:
-- does some computation to two Ints which might fail
compute :: Int -> Int -> Maybe Int
-- actual logic
main :: Int -> Int -> Int
main x y = do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
-- does some Int calculation to first, second and third
What I intend is for first, second, and third to have the actual Int values, taken out of the Maybe context, but doing the way above makes Haskell complain about not being able to match types of Maybe Int with Int.
Is there a way to do this? Or am I heading towards the wrong direction?
Pardon me if some terminology is wrongly used, I'm new to Haskell and still trying to wrap my head around everything.
EDIT
main has to return an Int, without being wrapped in Maybe, as there is another part of the code using the result of mainas Int. The results of a single compute might fail, but they should collectively pass (i.e. at least one would pass) in main, and what I'm looking for is a way to use do notation to take them out of Maybe, do some simple Int calculations to them (e.g. possibly treating any Nothing returned as 0), and return the final value as just Int.
Well the signature is in essence wrong. The result should be a Maybe Int:
main :: Int -> Int -> Maybe Int
main x y = do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
return (first + second + third)
For example here we return (first + second + third), and the return will wrap these in a Just data constructor.
This is because your do block, implicitly uses the >>= of the Monad Maybe, which is defined as:
instance Monad Maybe where
Nothing >>=_ = Nothing
(Just x) >>= f = f x
return = Just
So that means that it will indeed "unpack" values out of a Just data constructor, but in case a Nothing comes out of it, then this means that the result of the entire do block will be Nothing.
This is more or less the convenience the Monad Maybe offers: you can make computations as a chain of succesful actions, and in case one of these fails, the result will be Nothing, otherwise it will be Just result.
You can thus not at the end return an Int instead of a Maybe Int, since it is definitely possible - from the perspective of the types - that one or more computations can return a Nothing.
You can however "post" process the result of the do block, if you for example add a "default" value that will be used in case one of the computations is Nothing, like:
import Data.Maybe(fromMaybe)
main :: Int -> Int -> Int
main x y = fromMaybe 0 $ do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
return (first + second + third)
Here in case the do-block thus returns a Nothing, we replace it with 0 (you can of course add another value in the fromMaybe :: a -> Maybe a -> a as a value in case the computation "fails").
If you want to return the first element in a list of Maybes that is Just, then you can use asum :: (Foldable t, Alternative f) => t (f a) -> f a, so then you can write your main like:
-- first non-failing computation
import Data.Foldable(asum)
import Data.Maybe(fromMaybe)
main :: Int -> Int -> Int
main x y = fromMaybe 0 $ asum [
compute x y
compute (x+2) (y+2)
compute (x+4) (y+4)
]
Note that the asum can still contain only Nothings, so you still need to do some post-processing.
Willem's answer is basically perfect, but just to really drive the point home, let's think about what would happen if you could write something that allows you to return an int.
So you have the main function with type Int -> Int -> Int, let's assume an implementation of your compute function as follows:
compute :: Int -> Int -> Maybe Int
compute a 0 = Nothing
compute a b = Just (a `div` b)
Now this is basically a safe version of the integer division function div :: Int -> Int -> Int that returns a Nothing if the divisor is 0.
If you could write a main function as you like that returns an Int, you'd be able to write the following:
unsafe :: Int
unsafe = main 10 (-2)
This would make the second <- compute ... fail and return a Nothing but now you have to interpret your Nothing as a number which is not good. It defeats the whole purpose of using Maybe monad which captures failure safely. You can, of course, give a default value to Nothing as Willem described, but that's not always appropriate.
More generally, when you're inside a do block you should just think inside "the box" that is the monad and don't try to escape. In some cases like Maybe you might be able to do unMaybe with something like fromMaybe or maybe functions, but not in general.
I have two interpretations of your question, so to answer both of them:
Sum the Maybe Int values that are Just n to get an Int
To sum Maybe Ints while throwing out Nothing values, you can use sum with Data.Maybe.catMaybes :: [Maybe a] -> [a] to throw out Nothing values from a list:
sum . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]
Get the first Maybe Int value that's Just n as an Int
To get the first non-Nothing value, you can use catMaybes combined with listToMaybe :: [a] -> Maybe a to get Just the first value if there is one or Nothing if there isn't and fromMaybe :: a -> Maybe a -> a to convert Nothing to a default value:
fromMaybe 0 . listToMaybe . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]
If you're guaranteed to have at least one succeed, use head instead:
head . catMaybes $ [compute x y, compute (x+2) (y+2), compute (x+4) (y+4)]

Haskell: How to use random integer from randomRIO in a function that returns a boolean

I am new to Haskell and i'm having a problem with using the IO Int from randomRIO function. My goal is to get a random Int value, say r, and to return True if r < x or false otherwise, but i don't know how to do it.
my function should look like:
randomCompare :: Int->Bool
randomCompare x
| x < r = True -- somehow i want to r <- randomRIO(start,end)
| otherwise = False
I know there is a designed intention with keeping IO vals in context for purity etc.. but i don't see why using a random number for a Boolean function should be "bad".
Thanks.
import System.Random(randomIO)
randomCompare :: Int -> IO Bool
randomCompare x = do
r <- randomIO
return $ x < r
IO is neither good nor bad, it just declares that your function has side effects. Here the side effect is modifying the state of the global random number generator, so that a subsequent call to randomIO will give another number (it wouldn't be random if it was constant !).
IO does force all calling functions to be IO too (the ones that want to use the IO Bool). However, if a calling function is IO only by consuming this IO Bool, if it has no other side effects, then you can separate it as a pure function f :: Bool -> SomeType and functorially apply it on the IO, ie
f <$> randomCompare i
So the IO monad only costs you to replace the ordinary function call $ by the functorial fmap, also noted <$>. Is it so much longer to type ?
If you absolutely want to leave the IO monad (why ?), you can also draw all the random values you need first, store them in a list, then apply pure functions on that list.

How to generate random array in Haskell?

How can I generate random array using Data.Array?
I have function, that gives me a random number:
randomNumber :: (Random r) => r -> r -> IO r
randomNumber a b = getStdRandom (randomR (a,b))
And then I'm trying to use function from Data.Array to generate list
assocs $ array (1,100) [(i,i) | i <- (randomNumber 1 10)]
I know, that the type of randomNumber is IO, is there any method to convert IO Int -> Int? Or I need to use other methods to get random list? Should I do these functions with bind operator in do block?
You should use functions to generate random list from a generator, that are pure, and then use getStdRandom:
randomList :: Int -> Int -> IO [Int]
randomList a b = getStdGen >>= return . randomRs (a,b)
The function that you need is randomRs. Then you set the generator to stdGen with getStdGen and you have your generator.
The function randomList first gets the standard generator with getStdGen and then passes it to randomRs. Note that randomList can be rewritten without hiding the generator parameter:
randomList a b = getStdGen >>= \gen -> return (randomRs (a,b) gen)
I'll continue as long as #mariop's answer tells about lists, not arrays, and try to explain a nature of Haskell randomness a little more.
(if you're not interested in theory, skip to the (tl;dr) section)
At first, let's choose a signature for our presumed function. I'll consider that you need a plain array (as in C or Java), indexed by consecutive natural numbers (if my guessing is wrong, please correct).
As you may know, all Haskell functions are pure and deterministic, so each function must always return same results for the same arguments. That's not the case of random, of course. The solution is to use pseudorandom values, where we have a generator. A generator itself is a complicated function that have an internal hidden state called seed, and can produce a value and a new generator with a new seed (which then can produce a new (value, generator) pair and so on). A good generator is built in way that the next value could not be predicted from the previous value (when the we don't know the seed), so they appear as random to the user.
In fact, all major random implementations in most languages are
pseudorandom because the "true" random (which gets its values from the
sources of "natural" randomness, called entropy, such as CPU temperature) is
computatively expensive.
All so-called random functions in Haskell are dealing with the generator in some way. If you look at methods from the Random typeclass, they are divided in two groups:
Those which get the random generator explicitly: randomR, random and so on. You can build an explicit generator, initialized with a seed, with mkStdRandom (or even make your own).
Those which work in the IO monad: randomIO, randomRIO. They actually get the generator from the environment "carried" within the IO monad (with getStdRandom), and give it to function from the first group.
So, we can organize our function in either way:
--Arguments are generator, array size, min and max bound
generateArray :: (RangomGen g, Random r) => g -> Int -> r -> r -> Array Int r
or
--Arguments are array size, min and max bound
generateArray :: Random r => Int -> r -> r -> IO (Array Int r)
Because Haskell is lazy, there is no need to make a fixed set of random values — we can make an infinite one and take as many values as we need. The infinite list of random bounded values is produced by the randomRs function.
(tl;dr)
If the array is consecutive, the easier way is to build it from a plain values list rather than assocs (key, value) list:
generateArray gen size min max =
listArray (0, size - 1) $ randomRs (min, max) gen
or
generateArray size min max =
getStdGen >>= return . listArray (0, size - 1) . randomRs (min, max)

Storing values in a data structure Haskell

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

Resources