2012-09-09 8 views
5

Data.Array non fornisce pieghe per il tipo Array. (Ch. 12)Perché Haskell non fornisce pieghe per array monodimensionali?

In Real World Haskell, la ragione si dice che sia che Array s potrebbero essere piegati in modo differente in base alle esigenze del programmatore:

Prima di tutto, ci sono diversi tipi di pieghe che hanno un senso. Potremmo ancora voler piegare i singoli elementi, ma ora abbiamo la possibilità di ripiegare anche su righe o colonne. Oltre a questo, per la piegatura elemento-a-tempo, non ci sono più solo due sequenze per attraversare.

Non è esattamente vero per List s? È molto comune rappresentare ad es. una matrice con un multidimensionale List, ma esistono ancora pieghe definite per unidimensionale List s.

Qual è la sottigliezza che mi manca? È che un multidimensionale Array è sufficientemente diverso da uno Array di Array s?

Edit: Hm, anche multidimensionali array non hanno pieghe definite, sotto forma di istanze di Data.Foldable [0] Quindi, come si fa che in sintonia con la Haskell mondo reale preventivo.?

[0] http://hackage.haskell.org/packages/archive/base/4.6.0.0/doc/html/Data-Foldable.html

+0

La differenza tra gli array multidimensionali e gli elenchi annidati è che tutti gli array hanno essenzialmente lo stesso tipo: 'Array Int e',' Array (Int, Int) e', 'Array (Int, Int, Int) e' .... Quindi non puoi creare una funzione che è definita solo per matrici monodimensionali, mentre 'foldr' prende una lista di liste e la elabora lista per lista, invece di concatenare tutte le liste ed elaborarla elemento per elemento. –

risposta

8

Dal momento che si parla la differenza tra un "multidimensionale" Array e un Array di Array s, che illustreranno il punto di bene, a fianco di un confronto con le liste.

Una piega (nel senso di classe Foldable) è un'operazione intrinsecamente lineare, proprio come le liste sono una struttura intrinsecamente lineare; una piega destra caratterizza completamente una lista facendo corrispondere i suoi costruttori uno-a-uno con gli argomenti a foldr.Mentre è possibile definire funzioni come foldl, c'è una chiara scelta di una piega canonica standard.

Array non ha una struttura trasparente che possa essere abbinata in una sola volta in una piega. È un tipo astratto, con accesso a singoli elementi forniti da valori di indice, che possono essere di qualsiasi tipo che abbia un'istanza Ix. Quindi non solo non esiste un'unica scelta ovvia per implementare una piega, non esiste anche una struttura lineare intrinseca. Succede così che Ix ti consente di enumerare un intervallo di indici, ma questo è più un dettaglio di implementazione che altro.

Che dire di multidimensionale Array s? Non esistono davvero, in quanto tali. Ix definisce le istanze per le tuple di tipi che sono anche istanze e se vuoi pensare a tuple come un tipo di indice per un "multidimensionale" Array, vai avanti! Ma sono ancora solo tuple. Ovviamente, Ix mette un ordine lineare su quelle tuple, ma che cos'è? Riesci a trovare qualcosa nella documentazione che ti dice?

Quindi, penso che possiamo tranquillamente dire che piegando un multidimensionale Array utilizzando l'ordine definito dalla Ix è saggio a meno che non si ha realmente importa in che ordine si ottiene gli elementi in.

Per un Array di Array s , d'altra parte, c'è un solo modo ragionevole per combinarli, proprio come gli elenchi annidati: piegare ogni interno Array separatamente in base al proprio ordine di elementi, quindi piegare il risultato di ciascuno secondo l'ordine degli elementi Array esterno.


Ora, si potrebbe ragionevolmente obiettare che, poiché non c'è alcun tipo di distinzione tra una dimensione e multidimensionale Array s, e l'ex può essere assunta per avere un ordinamento piega ragionevole sulla base dell'istanza Ix, perché non basta usare quell'ordine di default? C'è già una funzione che restituisce gli elementi di un Array in un elenco, dopo tutto.

Come risulta, la libreria stessa sarebbe d'accordo con te, perché è esattamente ciò che fa l'istanza Foldable.

4

c'è un modo naturale per piegare le liste, che è foldr. Notare i tipi di costruttori della lista:

(:) :: a -> [a] -> [a] 
[] :: [a] 

Sostituzione delle occorrenze di [a] con b, otteniamo questi tipi:

f :: a -> b -> b 
z :: b 

E ora, naturalmente, il tipo di foldr si basa su questo principio :

foldr :: (a -> b -> b) -> b -> [a] -> b 

Quindi, dato la costruzione/la semantica di osservazione di liste, foldr è quella di che mos t naturale. Puoi leggere il tipo "dimmi cosa fare con uno (:) e cosa fare con uno [], e mi libererò di un elenco per te".

Array non ha questa proprietà; si costruisce un array da un elenco di associazioni (Ix i => [(i,a)]) e il tipo non espone realmente alcuna struttura ricorsiva: un array non viene generato da altri array tramite un costruttore ricorsivo come un albero o un albero.

+0

+1 per "dimmi cosa fare con un' (:) 'e cosa fare con un' [] ', e mi libererò di una lista per te." - mi piace veramente! – epsilonhalbe

Problemi correlati