0

I'm currently working on a program in Haskell (which I am very new to) where I need to randomly generate co-ordinates and use them around the program in several places, however, I don't want to be threading IO around the whole program, nor the seed. I saw this link where they use num <- randomIO :: IO Float however I keep getting - Couldn't match type `IO' with `[]' Expected type: [Float]. I in theory need the co-ordinates to be integer values, so if there is a better way of doing it that would be great! The full stack is below:

Couldn't match type `IO' with `[]'
      Expected type: [Float]
        Actual type: IO Float
    * In a stmt of a 'do' block: y <- randomIO :: IO Float

An example of the code that is causing an error.

import Data.List
import System.Random

someF :: [[Char]]
someF = do
            ytemp <- randomIO :: IO Float
            []
noo2171k
  • 9
  • 5
  • 5
    You _can't_ generate random numbers without treading either `IO` (or a more specialised monad) or seeds through the program, for [quite fundamental reasons](https://en.wikipedia.org/wiki/Referential_transparency). One thing you could do is generate an infinite list of random numbers up front, and then just consume that – but this is in practice hardly different from passing around a `Gen`, except the latter gives you more flexibility. Really, the best option is to use a monad. Not necessarily `IO` but [`RVar`](https://hackage.haskell.org/package/random-fu-0.2.7.7/docs/Data-Random.html#t:RVar). – leftaroundabout Dec 22 '20 at 20:01
  • do explore [tag:do-notation] in case you're not well versed in it. you do not show the [mcve] here, but it looks like your `do` block's type is `[] a` but `randomIO :: IO a`, and `[]` is not `IO`. the Monad must be the same, all throughout a given `do` block. – Will Ness Dec 22 '20 at 20:07
  • @WillNess I've added a minimum reproducible example! :) – noo2171k Dec 22 '20 at 20:38
  • 1
    Your example does not produce an error message like the one you posted. – leftaroundabout Dec 22 '20 at 20:44
  • @leftaroundabout sorry about that, I've updated the example! :D – noo2171k Dec 22 '20 at 21:05

1 Answers1

2
someF :: [[Char]]
someF = do { ... }

Here you have do block, but it's not in an IO action. That in itself is actually ok: do blocks can be in other types but IO, but they need be in a monadic type. It so happens that lists are also monadic, i.e. the compiler treats this as

someF :: [] [Char]
someF = do { ... }

(where [] is not the empty list, but the type-level constructor for list-types).

...This is analogous to

someF :: IO [Char]
someF = do { ... }

in which case you could have ytemp <- randomIO in the do block. Conversely, in a list-monad do block you could have, for instance,

  ytemp <- [1, 2, 5.3] :: [Float]

So this is why you get that error message: the compiler requires something of type [...], IOW [] (...), but you give it something of type IO (...) instead.

If you need to generate random values in the middle of your code, then you must have a suitable monad around (or explicitly passed seeds).

someF :: IO [[Char]]
someF = do
    ytemp <- randomIO :: IO Float
    return []
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319