简体   繁体   English

尝试打印出随机 IP 列表,但在 Haskell 中不断遇到错误

[英]Trying to print out a list of random IPs but keep encountering errors in Haskell

I am not very experienced in Haskell so I am not too sure what's going on.我对 Haskell 不是很有经验,所以我不太确定发生了什么。 I want to generate a list of random IP addresses and print them out but I keep encountering the errors below:我想生成一个随机 IP 地址列表并将它们打印出来,但我一直遇到以下错误:

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.您的问题都源于未正确处理 IO 。

First problem: createList calls randomIP , and randomIP 's result is in IO.第一个问题: createList调用randomIPrandomIP的结果在 IO 中。 Thus, createList must have its result in IO too.因此, createList的结果也必须在 IO 中。 So change createList:: Int -> [[Char]] -> [[Char]] to createList:: Int -> [[Char]] -> IO [[Char]] .所以将createList:: Int -> [[Char]] -> [[Char]]更改为createList:: Int -> [[Char]] -> IO [[Char]]

Second problem: Since createList 's result is in IO, the recursive call to itself must unwrap the IO.第二个问题:由于createList的结果在 IO 中,因此对自身的递归调用必须解开 IO。 So change let mylist3 = createList (n-1) mylist2 to mylist3 <- createList (n-1) mylist2 .所以将let mylist3 = createList (n-1) mylist2mylist3 <- createList (n-1) mylist2

Third problem: Since createList 's result is in IO, main 's call to it must unwrap the IO.第三个问题:由于createList的结果在 IO 中,所以main对其的调用必须解开 IO。 So change let mylist = createList maxtests [] to mylist <- createList maxtests [] .所以将let mylist = createList maxtests []更改为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 .另外,请注意,您不必要地重新实现了 Haskell 中已内置的一些函数: replicateMintercalatemap

To make use of intercalate and map , change let myip = (show (myarr.. 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3))要使用intercalatemap ,请更改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 = (show (myarr.. 0)) ++ "." ++ (show (myarr !! 1)) ++ "." ++ (show (myarr !! 2)) ++ "." ++ (show (myarr !! 3)) let myip = intercalate "." (map show myarr) 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:使用replicateM需要更大的更改,所以我将向您展示结果:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM