Siete alla ricerca di una lista eterogenea, che la maggior parte non lo fanno Haskellers piace particolarmente anche se loro stessi hanno chiesto la stessa domanda quando prima imparare Haskell.
Lei scrive:
shapes :: (Shape t) => [t]
Questo dice la lista è di tipo t
, che sono tutti uguali e capita di essere una forma (la stessa forma!). In altre parole - no, non dovrebbe funzionare come l'hai.
Due modi comuni per gestirlo (un modo Haskell 98, poi un modo più elaborato che Non consiglio secondo) sono:
utilizzare un nuovo tipo di sindacali staticamente i sottotipi di interesse:
data Foo = F deriving Show
data Bar = B deriving Show
data Contain = CFoo Foo | CBar Bar deriving Show
stuffExplicit :: [Contain]
stuffExplicit = [CFoo F, CBar B]
main = print stuffExplicit
Questo è bello visto che è diretto e non si perde alcuna informazione su ciò che è contenuto nella lista. È possibile determinare che il primo elemento è un Foo
e il secondo elemento è un Bar
. Lo svantaggio, come probabilmente già sapete, è che è necessario aggiungere esplicitamente ciascun tipo di componente creando un nuovo costruttore di tipo Contain
. Se questo non è desiderabile, continua a leggere.
Tipi Uso esistenziali: Un'altra soluzione comporta la perdita di informazioni circa gli elementi - basta conservare, ad esempio, la conoscenza che gli elementi sono in una classe particolare. Di conseguenza, puoi utilizzare solo le operazioni da quella classe sugli elementi della lista. Ad esempio, il seguito sarà solo ricordare gli elementi sono della classe Show
, quindi l'unica cosa che si può fare per gli elementi sono funzioni d'uso che sono polimorfici in Show
:
data AnyShow = forall s. Show s => AS s
showIt (AS s) = show s
stuffAnyShow :: [AnyShow]
stuffAnyShow = [AS F, AS B]
main = print (map showIt stuffAnyShow)
Questo richiede alcune estensioni al linguaggio Haskell , ovvero ExplicitForAll
e ExistentialQuantification
. Abbiamo dovuto definire esplicitamente showIt
(utilizzando la corrispondenza dei modelli per decostruire il tipo AnyShow
) perché non è possibile utilizzare i nomi dei campi per i tipi di dati che utilizzano la quantificazione esistenziale.
Non ci sono più soluzioni (si spera un'altra risposta utilizzerà Data.Dynamic
- se nessuno lo fa e sei interessato poi leggere su di esso e si sentono liberi di inviare tutte le domande che la lettura genera).
http://www.haskell.org/haskellwiki/Heterogenous_collections –
Ero consapevole di collezioni eterogenee, ma era qualcosa che volevo evitare. – Arlen