I am not very experienced in Haskell so I am not too sure what's going on. I want to generate a list of random IP addresses and print them out but I keep encountering the errors below:
My code:
import System.Random (randomRIO)
import Data.List
import Control.Monad.Cont
main :: IO ()
main = do
let maxtests = 5
let mylist = createList maxtests []
forM_ mylist $ \ip -> do
print ip
createList :: Int -> [[Char]] -> [[Char]]
createList 0 mylist = return mylist
createList n mylist = do
myarr <- randomIp 4
let myip = (show (myarr !! 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
let mylist2 = mylist ++ [myip]
let mylist3 = createList (n-1) mylist2
return mylist3
randomIp :: Int -> IO([Int])
randomIp 0 = return []
randomIp n = do
r <- randomRIO (0,255)
rs <- randomIp (n-1)
return (r:rs)
Error messages when I compile:
test2.hs:13:23: error:
* Couldn't match type `[Char]' with `Char'
Expected type: [[Char]]
Actual type: [[[Char]]]
* In the expression: return mylist
In an equation for `createList':
createList 0 mylist = return mylist
|
13 | createList 0 mylist = return mylist
| ^^^^^^^^^^^^^
test2.hs:15:14: error:
* Couldn't match type `IO' with `[]'
Expected type: [[Int]]
Actual type: IO [Int]
* In a stmt of a 'do' block: myarr <- randomIp 4
In the expression:
do myarr <- randomIp 4
let myip
= (show (myarr !! 0))
++
"."
++
(show (myarr !! 1))
++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
let mylist2 = mylist ++ ...
let mylist3 = createList (n - 1) mylist2
....
In an equation for `createList':
createList n mylist
= do myarr <- randomIp 4
let myip = ...
let mylist2 = ...
....
|
15 | myarr <- randomIp 4
| ^^^^^^^^^^
test2.hs:19:5: error:
* Couldn't match type `[Char]' with `Char'
Expected type: [[Char]]
Actual type: [[[Char]]]
* In a stmt of a 'do' block: return mylist3
In the expression:
do myarr <- randomIp 4
let myip
= (show (myarr !! 0))
++
"."
++
(show (myarr !! 1))
++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
let mylist2 = mylist ++ ...
let mylist3 = createList (n - 1) mylist2
....
In an equation for `createList':
createList n mylist
= do myarr <- randomIp 4
let myip = ...
let mylist2 = ...
....
|
19 | return mylist3
| ^^^^^^^^^^^^^^
Would appreciate any pointers on what I'm doing wrong.
Your problems all stem from not handling IO correctly.
First problem: createList
calls randomIP
, and randomIP
's result is in IO. Thus, createList
must have its result in IO too. So change createList:: Int -> [[Char]] -> [[Char]]
to createList:: Int -> [[Char]] -> IO [[Char]]
.
Second problem: Since createList
's result is in IO, the recursive call to itself must unwrap the IO. So change let mylist3 = createList (n-1) mylist2
to mylist3 <- createList (n-1) mylist2
.
Third problem: Since createList
's result is in IO, main
's call to it must unwrap the IO. So change let mylist = createList maxtests []
to mylist <- createList maxtests []
.
With all of those changes, it compiles.
Bonus material below here:
Also, note that you've unnecessarily reimplemented a few functions that are already built in to Haskell: replicateM
, intercalate
, and map
.
To make use of intercalate
and map
, change let myip = (show (myarr.. 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
let myip = (show (myarr.. 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
let myip = (show (myarr.. 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))
to let myip = intercalate "." (map show myarr)
let myip = intercalate "." (map show myarr)
.
Making use of replicateM
requires much larger changes, so I'll just show you the result:
import System.Random (randomRIO)
import Data.List
import Control.Monad.Cont
main :: IO ()
main = do
let maxtests = 5
mylist <- createList maxtests
forM_ mylist $ \ip -> do
print ip
createList :: Int -> IO [[Char]]
createList n = replicateM n $ do
myarr <- randomIp 4
let myip = intercalate "." (map show myarr)
return myip
randomIp :: Int -> IO [Int]
randomIp n = replicateM n $ do
r <- randomRIO (0,255)
return r
You can even continue the refactoring further if you want, to something like this:
import System.Random (randomRIO)
import Control.Monad
import Data.Foldable
import Data.List
main :: IO ()
main = do
let maxtests = 5
mylist <- createList maxtests
for_ mylist print
createList :: Int -> IO [[Char]]
createList n = replicateM n $ intercalate "." . map show <$> randomIp 4
randomIp :: Int -> IO [Int]
randomIp n = replicateM n $ randomRIO (0,255)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.