I have a question that goes on how to work with monads. I have the following code:
import System.Random
import Data.Random.Normal
import Graphics.EasyPlot
import Data.List
import Data.Function
random' mean randomGen = zip x y
where
x = normals' (mean, 0.2) randomGen :: [Float]
y = normals' (mean, 0.2) randomGen :: [Float]
randomW1 randomGen = [[x,y] | (x,y) <- random' 1.0 randomGen]
main = do
randomGen <- getStdGen
let w1 = take 50 (randomW1 randomGen)
print w1
and it works fine. However, I think its limiting to bind the output of getStdGen
outside of randomW1
, and thought I could be able to bind the getStdGen
more directly to randomW1
by writing
w1 = take 50 (randomW1 =<< getStdGen)
I believe I have utilised the >>=
or =<<
to "pipe" monadic structures together, and replacing the use of do
and <-
. When I am doing as I suggest I discover that it
Couldn't match type ‘IO’ with ‘[]’
Expected type: [StdGen]
Actual type: IO StdGen
is there a way to use >>=
to replace the do
and <-
in this code?
main = do
w1 <- getStdGen >>= (return . take 50 . randomW1)
print w1
(parentheses not actually needed)
Personally, I dislike the style above, since >>= (return . f)
can be achieved with fmap f
in a simpler way, as follows:
main = do
w1 <- (take 50 . randomW1) `fmap` getStdGen
-- or: w1 <- take 50 . randomW1 <$> getStdGen
print w1
Removing the last <-
, we get:
main = print . take 50 . randomW1 =<< getStdGen
Here's a more systematic approach to derive the last one, step by step. Start from the beginning:
main = do
randomGen <- getStdGen
let w1 = take 50 (randomW1 randomGen)
print w1
Inline w1
:
main = do
randomGen <- getStdGen
print (take 50 (randomW1 randomGen))
Desugar do x <- m ; e
into m >>= \x -> e
. This is how the do
syntax is defined.
main = getStdGen >>= \randomGen -> print (take 50 (randomW1 randomGen))
Use composition for the last lambda:
main = getStdGen >>= print . take 50 . randomW1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With