繁体   English   中英

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

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

我对 Haskell 不是很有经验,所以我不太确定发生了什么。 我想生成一个随机 IP 地址列表并将它们打印出来,但我一直遇到以下错误:

我的代码:

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) 

我编译时的错误消息:

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
   |     ^^^^^^^^^^^^^^

将不胜感激任何关于我做错了什么的指示。

您的问题都源于未正确处理 IO 。

第一个问题: createList调用randomIPrandomIP的结果在 IO 中。 因此, createList的结果也必须在 IO 中。 所以将createList:: Int -> [[Char]] -> [[Char]]更改为createList:: Int -> [[Char]] -> IO [[Char]]

第二个问题:由于createList的结果在 IO 中,因此对自身的递归调用必须解开 IO。 所以将let mylist3 = createList (n-1) mylist2mylist3 <- createList (n-1) mylist2

第三个问题:由于createList的结果在 IO 中,所以main对其的调用必须解开 IO。 所以将let mylist = createList maxtests []更改为mylist <- createList maxtests []

通过所有这些更改,它可以编译。


奖金材料如下:

另外,请注意,您不必要地重新实现了 Haskell 中已内置的一些函数: replicateMintercalatemap

要使用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)) let myip = intercalate "." (map show myarr) let myip = intercalate "." (map show myarr)

使用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

如果您愿意,您甚至可以继续进一步重构,如下所示:

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