2

我有以下代码:

import Data.Array
import Control.Monad
import Data.Functor 
import System.Random (randomRIO)

randomList 0 = return []
randomList n = do
  r  <- randomRIO (1,6)
  rs <- randomList (n-1)
  return (r:rs) 

quicksort [] = []  
quicksort (x:xs) =   
    let smallerSorted = quicksort [a | a <- xs, a <= x]  
        biggerSorted = quicksort [a | a <- xs, a > x]  
    in  smallerSorted ++ [x] ++ biggerSorted  
  1. randomList - 创建一个给定长度的列表并用随机值填充它;
  2. quicksort - 快速排序列表。

我需要对创建的数组应用排序: quicksort (randomList 10),但发生错误:

"Couldn't match expected type‘ [a] ’with actual type IO [Int]’"
4

1 回答 1

3

您应该在程序中包含所有顶级名称的类型签名。如果您不认识它们,请加载文件并询问 GHCi: Main> :t randomList。然后将其复制粘贴到文件中(或根据您的需要先对其进行专门化)。将类型签名放在它描述的名称上方。

GHCI 说

randomList ::
  (System.Random.Random t, Num t, Num a, Eq a) => a -> IO [t]

但你很可能是说

randomList :: (System.Random.Random t, Num t) => Int -> IO [t]
randomList 0 = return []
randomList n = do
  r  <- randomRIO (1,6)    -- randomRIO (1,6) :: IO t  , r :: t
  rs <- randomList (n-1)   --             rs :: [t]
  return (r:rs)            --    r :: t , rs :: [t] 

一般来说,

randomRIO (1,6) :: (System.Random.Random a, Num a) => IO a

您投掷 6 面骰子n时间并将结果收集到一个列表中。顺便说一句,同样的事情是由

sequence $ replicate n (randomRIO (1,6))
===
replicateM n (randomRIO (1,6))

> :t \n -> replicateM n (randomRIO (1,6))
           :: (System.Random.Random a, Num a) => Int -> IO [a]

然后,GHCi 还告诉我们,

 quicksort :: Ord t => [t] -> [t]

但是randomList nIO [t],不是[t]。要获得[t]生活在里面的价值IO [t],你需要在里面做:

sortRandom :: (Ord t, Monad m) => m [t] -> m [t]
sortRandom randomlist = do
    xs <- randomlist        -- randomlist :: IO [t] , xs :: [t]
    let ys = quicksort xs
    return ys

以上可以简写为

sortRandom :: (Ord t, Monad m) => m [t] -> m [t]
sortRandom = liftM quicksort     -- for monads

或者

sortRandom :: (Ord t, Functor f) => f [t] -> f [t]
sortRandom = fmap quicksort      -- for functors

无论您喜欢哪个。两者都可以与IOmonad 一起使用,并且任何 monad 也是函子。所以最后你可以定义

foo :: Int -> IO [Int]
foo n = liftM quicksort $ replicateM n (randomRIO (1,6))
于 2019-04-20T17:17:20.600 回答