尝试打印出随机IP列表,但在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
   |     ^^^^^^^^^^^^^^

对于我在做什么错的任何指示,我们将不胜感激。

a21221266 回答:尝试打印出随机IP列表,但在Haskell中始终遇到错误

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

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

第二个问题:由于createList的结果在IO中,因此对其自身的递归调用必须解开IO。因此,将let mylist3 = createList (n-1) mylist2更改为mylist3 <- 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 = 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)
本文链接:https://www.f2er.com/3147895.html

大家都在问