2013-01-13 8 views
5

Esiste un modo efficiente per costruire una sezione (una vista sottoarray) da un IOArray o MArray in generale? Cioè, prendendo lo stesso array, limitando solo i limiti. La firma potrebbe essereAffettare un IOArray (o MArray in generale)

(MArray a e m, Ix i) => a i e -> i -> i -> m (a i e) 

Ad esempio, prendendo un array con limiti (1,1000) e fare una vista che dà accesso ad alcuni elementi con limiti (500,700) dell'array originale. Ho cercato la documentazione ma non ho trovato nessuna di tali funzioni.

+0

Quindi si desidera avere l'intervallo '[500..700]' _remapped_ a '[0..200]', o dovrebbe solo essere in qualche modo limitato (ad esempio, lanciare un'eccezione 'IO' quando si accede all'esterno la gamma)? Come si deve comportarsi con array multidimensionali con intervalli come '[(20,20) .. (40,40)]'? – leftaroundabout

+4

Non penso, ma se usi Data.Vector http://hackage.haskell.org/package/vector-0.10.0.1 puoi estrarre le sezioni. Ha anche regole di ottimizzazione della fusione, quindi sarà generalmente più efficiente. –

+0

@leftaroundabout Nessuna modifica necessaria. Fondamentalmente quello che voglio è avere lo stesso array il cui 'getBounds' segnala l'intervallo limitato (e forse l'accesso agli elementi esterni genera un'eccezione, ma questo non è necessario). –

risposta

5

Dato il modo in cui vengono implementati i tipi di array, questo non è qualcosa che sarebbe davvero una caratteristica di un array, il che probabilmente è il motivo per cui non esiste già nulla lungo queste linee.

Ricordare che un array è un blocco contiguo di memoria, quindi a un certo livello ogni array con elementi n ha limiti (0, n-1). Tuttavia, volere indici diversi da numeri interi che partono da zero è abbastanza comune che Haskell fornisce a type class per la definizione di limiti arbitrari e la conversione da un elemento all'interno di tali limiti a un indice intero basato su 0 per il blocco effettivo di memoria.

Ciò causa alcune difficoltà per ciò che si vuole fare perché si presume che i limiti di un array coprano l'intero intervallo. Quindi, se dovessi semplicemente creare una copia di un array esistente che usasse lo stesso chunk di memoria ma limiti diversi, gli indici non si allineano - nel tuo esempio, l'indice 500 nel sottoarray sarebbe lo stesso dell'indice 1 nell'originale array. Non d'aiuto.

L'approccio più semplice sarebbe quello di definire il proprio tipo di array che avvolge una matrice esistente e memorizza qualsiasi informazione aggiuntiva necessaria per tradurre gli indici, in modo che segnali i propri limiti come l'intervallo più piccolo, ma guarda le cose nell'involucro array basato sull'intera gamma. È quindi possibile utilizzare il tipo di array spostato ovunque (e assegnargli tutte le istanze previste, & c.) Con gli array appena creati utilizzando semplicemente gli stessi limiti della matrice "reale". Qui puoi eseguire qualsiasi traduzione di cui hai bisogno sugli indici, quindi questo approccio dovrebbe generalizzare anche ai tipi di indice che non hanno un ordine lineare (ad es., Array "multidimensionali" indicizzati da tuple).

Probabilmente potresti anche fare qualcosa che riguarda un wrapper attorno al tuo tipo di indice e dare alla versione wrapper una strana istanza Ix che traduce automaticamente le cose in qualche modo, il che ti permetterebbe di usare i tipi di array esistenti. Ciò sarebbe probabilmente più complicato per rendere il lavoro corretto, però.

Non credo che ci sia un modo per farlo senza cambiare il tipo di array o di indice.