La mancanza che si osserva è perché l'informazione di lunghezza non fa parte del tipo dell'elenco; poiché il controllore del tipo intende ragionare sui tipi, non è possibile specificare gli invarianti nelle proprie funzioni a meno che gli invarianti non siano nello tipo degli argomenti stessi o sui vincoli di classe di caratteri o le uguaglianze basate sulla famiglia. (Ci sono alcuni pre-processori di haskell, però, come Liquid Haskell, che ti permettono di annotare le funzioni con invarianti come questo che saranno controllati sulla compilazione.)
ci sono molte librerie haskell che offrono strutture di tipo elenco con lunghezza codificata nel tipo. Alcuni importanti sono lineare (con V
) e fisso-vettore.
L'interfaccia per V
più o meno così:
f :: V n a -> V n a -> V n a
g :: V n a -> V n a -> [a]
-- or --
g :: V n a -> V n a -> V ?? a -- if ?? can be determined at compile-time
Annotare il particolare modello della nostra prima firma tipo per g
: Prendiamo due tipi in cui ci stanno a cuore le lunghezze, e restituire un tipo che doesn 't cura la lunghezza, perdendo informazioni.
Nel secondo caso, se abbiamo do preoccuparsi della lunghezza del risultato, la lunghezza deve essere nota in fase di compilazione perché ciò abbia senso.
Si noti che V
da lineare in realtà non racchiude un elenco, ma un vettore dalla libreria di vettori. Richiede anche l'obiettivo (la libreria lineare, cioè), che è certamente un'enorme dipendenza da inserire se tutto ciò che si desidera è un vettore con codifica della lunghezza. Penso che il tipo vettoriale da vettori fissi usi qualcosa di più equivalente ad una normale lista haskell ... ma non ne sono del tutto sicuro. In ogni caso, ha un'istanza Foldable
, quindi è possibile convertirlo in un elenco.
Ricordate, naturalmente, che se avete intenzione di codificare lunghezze nelle vostre funzioni come questa ... Haskell/GHC deve essere in grado di vedere che il vostro typececk di implementazione!Per la maggior parte di queste librerie, Haskell sarà in grado di digitare tipicamente cose come questa (se si attaccano cose come zipping e fmapping, binding, ap-ping). Per la maggior parte dei casi utili questo è vero ... tuttavia, a volte la tua implementazione non può essere "dimostrata" dal compilatore, quindi dovrai "provarla" per te nella tua testa e usare una sorta di coercizione non sicura .
Stai bene aggiungendo un altro strumento alla casella degli strumenti? Haskell liquido può codificare facilmente una tale proprietà, ma il sistema di tipo Haskell GHC richiederebbe un nuovo tipo, come un GADT con numeri Peano. –
L'utilizzo di un elenco di lunghezza indicizzata rende anche le funzioni incompatibili con le funzioni che funzionano sugli elenchi ordinari e si perde (o si deve reimplementare) la fusione delle liste di GHC. –
Thomas, grazie per il suggerimento di Liquid Haskell (citato anche nella risposta di Justin). Se è maturo (cioè non sperimentale) e non influenza negativamente le prestazioni del codice compilato, non sarei contrario all'aggiunta di toolkit per risolvere la risposta. Reid, grazie per la tua osservazione; perdere la compatibilità con le funzioni esistenti/elenco-fusion è qualcosa che non vedo l'ora di evitare. – sircolinton