Aufbau einer Liste in Haskell
Ich möchte eine Liste zufälliger Ganzzahlen ohne Duplikate erstellen. Als ersten Schritt habe ich eine Funktion, die eine Liste von n Zufallsstichproben erstellt. Wie schreibt man dies auf eine eher Haskell-idiomatische Weise, bei der keine leere Liste übergeben werden muss, um die Liste zu starten? Ich bin sicher, ich vermisse etwas Grundlegendes und Grundlegendes.
-- make a list of random integers.
-- takes a size, and an empty list.
-- returns a list of that length of random numbers.
f :: Int -> [Int] -> IO [Int]
f l xs | length xs >= l = return (xs)
f l xs = do
r <- randomRIO (1, 40) :: IO Int
f l $ r : x
Verwendung:
*Main> f 6 []
[10,27,33,35,31,28]
Letztendlich wird diese Funktion gefiltert, um nach doppelten Einfügungen zu suchen, aber das ist eine separate Frage. Dies mag zwar wie Hausaufgaben aussehen, ist es aber nicht, aber Teil meines eigenen Versuchs, die staatliche Monade, wie sie für die Zufallszahlengenerierung verwendet wird, in den Griff zu bekommen und festzustellen, dass ich an einem viel früheren Ort festsitze.
Nun, Sie können die Ausgabe des rekursiven Aufrufs bearbeiten:
f :: Int -> IO [Int]
f 0 = return []
f n = do
r <- randomRIO (1, 40)
xs <- f (n-1)
return $ r : xs
Beachten Sie jedoch, dass es wichtig ist, dass die Operation, die Sie für das Ergebnis ausführen, schnell ist. In diesem Fall r : xs
ist die Zeit konstant. Wenn Sie jedoch die letzte Zeile durch (sagen wir) ersetzen:
return $ xs ++ [r]
Dies würde die Komplexität der Funktion von linear zu quadratisch ändern, da bei jedem ++
Anruf die gesamte Sequenz zuvor generierter Nummern gescannt werden muss, bevor die neue angehängt wird.
Sie können jedoch einfach Folgendes tun:
f n = sequence $ replicate n (randomRIO (1, 40))
replicate
Erstellt eine [IO Int]
Liste der Länge n
von randomRIO
Aktionen und sequence
nimmt eine [IO a]
und verwandelt sie in eine, IO [a]
indem alle Aktionen der Reihe nach ausgeführt und die Ergebnisse gesammelt werden.
Noch einfacher können Sie replicateM
die bereits gewünschte Funktion verwenden:
import Control.Monad(replicateM)
f n = replicateM n (randomRIO (1, 40))
oder punktfrei:
f :: Int -> IO [Int]
f = flip replicateM $ randomRIO (1, 40)