I'm quite new in Haskell and I'm trying to create a function that generates an array of finite Numbers taking into account some starting and ending bound . If I use the following function ...
finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> g -> ([a], g)
finiteRandoms 0 g = ([], g)
finiteRandoms n g =
let (value, newGen) = randomR (20,100) g
(restOfList, finalGen) = finiteRandoms (n-1) newGen
in (value:restOfList, finalGen)
and I run the following command ...
finiteRandoms 3 (mkStdGen 3)
I obtain an array of Int with the new generator
([61,33,82],StdGen {unStdGen = SMGen 9186733390819170434 2092789425003139053})
What I'm trying to do is to add two new parameters to the function that marks the starting and ending point . In the function I have shared, it represents the numbers 20 and 100 . Something like this
finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> n -> n-> g -> ([a], g)
finiteRandoms 0 start end g = ([], g)
finiteRandoms n start end g =
let (value, newGen) = randomR (start,end) g
(restOfList, finalGen) = finiteRandoms (n-1) newGen
in (value:restOfList, finalGen)
But when I load it through ghci I get the following error
randomSample.hs:19:10: error: [GHC-83865]
• Couldn't match expected type: n -> g0 -> ([a0], g0)
with actual type: (a1, b)
• In the pattern: (restOfList, finalGen)
In a pattern binding:
(restOfList, finalGen) = finiteRandoms (n - 1) newGen
In the expression:
let
(value, newGen) = randomR (start, end) g
(restOfList, finalGen) = finiteRandoms (n - 1) newGen
in (value : restOfList, finalGen)
• Relevant bindings include
value :: n (bound at randomSample.hs:18:11)
end :: n (bound at randomSample.hs:17:24)
start :: n (bound at randomSample.hs:17:18)
n :: n (bound at randomSample.hs:17:16)
finiteRandoms :: n -> n -> n -> g -> ([a], g)
(bound at randomSample.hs:16:2)
|
19 | (restOfList, finalGen) = finiteRandoms (n-1) newGen
| ^^^^^^^^^^^^^^^^^^^^^^
randomSample.hs:20:11: error: [GHC-25897]
• Couldn't match expected type ‘a’ with actual type ‘n’
‘n’ is a rigid type variable bound by
the type signature for:
finiteRandoms :: forall n g a.
(Eq n, Num n, RandomGen g, Random a, Num a) =>
n -> n -> n -> g -> ([a], g)
at randomSample.hs:15:2-92
‘a’ is a rigid type variable bound by
the type signature for:
finiteRandoms :: forall n g a.
(Eq n, Num n, RandomGen g, Random a, Num a) =>
n -> n -> n -> g -> ([a], g)
at randomSample.hs:15:2-92
• In the first argument of ‘(:)’, namely ‘value’
In the expression: value : restOfList
In the expression: (value : restOfList, finalGen)
• Relevant bindings include
value :: n (bound at randomSample.hs:18:11)
end :: n (bound at randomSample.hs:17:24)
start :: n (bound at randomSample.hs:17:18)
n :: n (bound at randomSample.hs:17:16)
finiteRandoms :: n -> n -> n -> g -> ([a], g)
(bound at randomSample.hs:16:2)
|
20 | in (value:restOfList, finalGen)
| ^^^^^
Failed, no modules loaded.
How can I parametrized this two bounds (start/end) ? Thanks.
You forgot to add the start
and end
in the recursive call, start
and end
also need to be of type g
finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> a -> a -> g -> ([a], g)
finiteRandoms 0 start end g = ([], g)
finiteRandoms n start end g =
let (value, newGen) = randomR (start,end) g
(restOfList, finalGen) = finiteRandoms (n-1) start end newGen
in (value:restOfList, finalGen)
But likely, it is better to work with a helper function here:
finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => a -> a -> n -> g -> ([a], g)
finiteRandoms start end = go
where go 0 g = ([], g)
go n g =
let (value, newGen) = randomR (start,end) g
(restOfList, finalGen) = go (n-1) newGen
in (value:restOfList, finalGen)
We then for example generate five numbers between twenty and hundred with:
ghci> finiteRandoms 20 100 5 (mkStdGen 3)
([70,50,99,83,50],781515869 652912057)