Scegliere una carta da un mazzo mescolato

1

Sono abbastanza nuovo per Haskell anche se ho fatto qualche ML molte lune fa.

Sto provando a creare un mazzo di carte da gioco, mischiarle e poi distribuirle. Ho il mazzo e lo shuffle ordinati (di moda) ma non sono sicuro di cosa farò dopo.

Questo è quello che ho finora:

import System.Random
import Data.Array.IO
import Control.Monad

-- | Randomly shuffle a list
--   /O(N)/
shuffle :: [a] -> IO [a]
shuffle xs = do
        ar <- newArray n xs
        forM [1..n] $ \i -> do
            j <- randomRIO (i,n)
            vi <- readArray ar i
            vj <- readArray ar j
            writeArray ar j vi
            return vj
  where
    n = length xs
    newArray :: Int -> [a] -> IO (IOArray Int a)
    newArray n xs =  newListArray (1,n) xs

ranks=[2..14]

suits=[1,2,3,4]

cards=[(r,s) | r <- ranks, s<- suits]

deck=shuffle cards


myAction :: IO [(Integer, Integer)]
myAction = shuffle cards

main :: IO ()
main = do
    xs <- myAction
    print xs

Non c'era una ragione particolare per cui ho scelto quel list shuffler oltre al motivo per cui potevo interrogare (o almeno visualizzare) la lista risultante.

Mi piacerebbe essere in grado di estrarre gli elementi dal IO [(Integer, Integer)] restituito, ma non sono del tutto sicuro su come procedere. Capisco che non posso semplicemente convertirlo in una lista di vaniglia (questo è coperto sufficientemente altrove), quindi presumibilmente ho bisogno di:

  • estendi l'IO (monad?) in qualche modo
  • scrivi un elenco personalizzato di tuples shuffler
  • scrivi la mia monade
  • usa un altro metodo che non ho ancora imparato

Aneddoticamente, credo che questo possa essere fatto "non pulito" ma non voglio andare al programmatore dell'inferno finché non capisco quanto sono caldi gli incendi ...

Qualche idea sul modo migliore di procedere?

    
posta Robbie Dee 09.04.2014 - 13:51
fonte

1 risposta

2

In termini astratti, ciò che dovresti fare è spingere la parte IO come "alta" nel tuo codice il più possibile, in modo che il minor numero possibile di codice conosca IO.

In termini più concreti, per il tuo problema, shuffle e myAction non hanno bisogno di sapere su IO, e inoltre non hanno bisogno di sapere come viene generata la casualità. Hanno solo bisogno della casualità passata come parametro. Quindi, ciò che puoi fare è generare il valore casuale in main e quindi passarlo come valore puro a myAction e / o shuffle .

Dovresti finire con tipi come shuffle :: randomness -> [a] -> [a] e myAction :: randomness -> [a] , dove "casualità" è generata in main . Ora i tuoi valori di ritorno non sono inquinati con IO , ed è facile lavorarci con loro. *

AFAIK, questo schema - in cui dividi il tuo codice in porzioni "pure" e "impure" (e speri che la maggior parte di esso sia "puro" :)) - è piuttosto comune in Haskell.

*: se sei bloccato in IO , leggi su functors ( fmap ), applicativi ( liftA2 , <*> , ecc.), monadi ( liftM , >>= , ecc.) e sollevamento. È ancora un problema, ma usando quelli che puoi lavorare sulla parte a di IO a .

    
risposta data 09.04.2014 - 14:08
fonte

Leggi altre domande sui tag