Reputation: 11
Im trying to plot a random walk in haskell. Im useing getStdGen for the random nummbers. Im useing Chart.Easy for the plotting. Im a pleb at haskell and I cant understand the compiler error Im getting.
import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Cairo
import System.Random
main = toFile def "random_walk.png" $ do
layout_title .= "Random Walk"
setColors [opaque blue, opaque red]
g <- getStdGen
plot (line "random walk" [ take 100 $ walk (0,0) ( randoms g :: [Float])])
walk :: (Float, Float) -> [Float] -> [(Float, Float)]
walk (x,y) (dx:dy:list) = (x+dx,y+dy):(walk (x+dx,y+dy) list)
The error is:
[1 of 1] Compiling Main ( simple.hs, interpreted )
simple.hs:8:7: error:
* Couldn't match type `IO'
with `Control.Monad.Trans.State.Lazy.StateT
(Layout Float Float) (Control.Monad.Trans.State.Lazy.State CState)'
Expected type: Control.Monad.Trans.State.Lazy.StateT
(Layout Float Float)
(Control.Monad.Trans.State.Lazy.State CState)
StdGen
Actual type: IO StdGen
* In a stmt of a 'do' block: g <- getStdGen
In the second argument of `($)', namely
`do layout_title .= "Random Walk"
setColors [opaque blue, opaque red]
g <- getStdGen
plot
(line
"random walk" [take 100 $ walk (0, 0) (randoms g :: [Float])])'
In the expression:
toFile def "random_walk.png"
$ do layout_title .= "Random Walk"
setColors [opaque blue, opaque red]
g <- getStdGen
plot
(line
"random walk" [take 100 $ walk (0, 0) (randoms g :: [Float])])
|
8 | g <- getStdGen
| ^^^^^^^^^
Failed, no modules loaded.
Dose anyone understand? Can anyone help me? Any other comments?
After code was fixed, the reslut was this image.
Upvotes: 0
Views: 228
Reputation: 51129
The problem is that toFile
's third argument is an action in a special EC
monad. This monad can't do IO, so you can't include IO actions like getStdGen
in its do-block.
Instead, use a separate outer IO do-block to get the random number stream you need as a pure value, and then you can freely use it in the inner EC do-block, like so:
main :: IO ()
main = do
-- this is do-block for the IO monad
nums <- randomRs (-1,1) <$> getStdGen
toFile def "random_walk.png" $ do
-- this is the do-block for the EC monad
layout_title .= "Random Walk"
setColors [opaque blue, opaque red]
plot (line "random walk" [ take 100 $ walk (0,0) nums ])
walk :: (Float, Float) -> [Float] -> [(Float, Float)]
walk (x,y) (dx:dy:list) = (x+dx,y+dy):(walk (x+dx,y+dy) list)
Upvotes: 3