Per salvare esternamente le autorizzazioni dell'account utente (ad es. In DB), voglio rappresentare un elenco di elementi di un'enumerazione che ha un'istanza derivata Enum
come Int
.
Ogni bit del numero è visto come un flag (o booleano) che indica se l'elemento i-esimo è presente nell'elenco.
Inserendolo in parole diverse: ogni potenza di 2 rappresenta un elemento e la somma di tali poteri è un elenco di elementi unico.Rappresenta un elenco di enum a bit come Int
Esempio:
data Permissions = IsAllowedToLogin -- 1
| IsModerator -- 2
| IsAdmin -- 4
deriving (Bounded, Enum, Eq, Show)
enumsToInt [IsAllowedToLogin, IsAdmin] == 1 + 4 == 5
intToEnums 3 == intToEnums (1 + 2) == [IsAllowedToLogin, IsModerator]
La funzione di conversione di tale lista in un Int
è abbastanza facile da scrivere:
enumsToInt :: (Enum a, Eq a) => [a] -> Int
enumsToInt = foldr (\p acc -> acc + 2^fromEnum p) 0 . nub
Si noti che la risposta accettata contiene un'implementazione molto più efficace .
Ciò che veramente mi turba è la funzione di inversione. Immagino che dovrebbe avere questo tipo:
intToEnums :: (Bounded a, Enum a) => Int -> [a]
intToEnums = undefined -- What I'm asking about
Come devo affrontare questo problema?
Per cominciare, hai guardato [il 'Data.Bits' modulo] (http: //hackage.haskell .org/pacchetti/archive/base/ultima/doc/html/dati-Bits.html)? –
@C. A. McCann No, non ho! Pensi che sarà utile? – Jakub
Non penso che abbia qualcosa che fa esattamente quello che vuoi (anche se sembra qualcosa che dovrebbe esserci) ma ha un sacco di operazioni bit a bit che renderanno le cose più facili per te. –