2012-01-07 10 views

risposta

30

È molto più semplice se si guarda la definizione di StoreT itself.

Si può pensare a un "luogo" in una struttura più grande. Ad esempio, uno lens è solo a -> Store b a; si ottiene il valore del campo b e una funzione b -> a per reinserire un nuovo valore nel contesto più ampio.

Considerando nella sua forma semplificata, non trasformatore:

data Store s a = Store (s -> a) s 

instance Functor (Store s) where 
    fmap f (Store g s) = Store (f . g) s 

instance Extend (Store s) where 
    duplicate (Store f s) = Store (Store f) s 

instance Comonad (Store s) where 
    extract (Store f s) = f s 

cioè duplicate cambia il s -> a in un s -> Store s a che restituisce solo il luogo "aggiornata" dopo la sostituzione del valore, e extract ripristina l'originale un inserendo il valore nella struttura più grande.

Per quanto riguarda il suo rapporto con Stato va, si poteva guardare in questo modo:

type State s a = s -> (a, s) 
type Store s a = (s -> a, s) 
+15

Giusto per espandere la connessione tra Stato e Negozio, tutte le monadi derivano da una composizione di funzioni aggiuntive. È comunemente noto che i functors '(r -> _)' (aka Reader) e '(_, r)' (anche capovolto, ma non si adatta alla solita presentazione di State in Haskell, e non può essere un Istanza di Functor in Haskell) sono aggiunti, e se li componi in un modo ('s -> (_, s)') otterrai una monade, e se li componi nell'altro modo ('(s -> _, s) ') otterrai una comonad. – copumpkin

+0

@copumpkin: È '(_, r)' che non può essere un Functor, non è vero? '(r, _)' è solo 'instance Functor ((,) r)'. – ehird

+0

Sì, scusate, ho erroneamente commentato questa parentesi :) – copumpkin

33

Data la seguente definizione di negozio,

data Store s a = Store { peek :: s -> a, pos :: s } 

Mi piace pensare di un Store come un grande magazzino pieno di valori di tipo a. Ogni valore di tipo a viene inserito in una posizione contrassegnata da un valore di indice di tipo s. Finalmente c'è un carrello elevatore parcheggiato in posizione pos. Il carrello elevatore può essere utilizzato a extract un valore di tipo a dal negozio estraendo il valore da dove è parcheggiato. È possibile utilizzare seek per spostare il carrello elevatore su una nuova posizione assoluta o utilizzare seeks per spostare il carrello elevatore in una nuova posizione relativa. Per aggiornare tutti i valori del negozio utilizzare fmap. Infine extend f è simile a fmap eccetto che in sostituzione diabbiamo f :: Store s a -> a' che consente alla funzione di aggiornamento non solo di accedere al valore in fase di aggiornamento, ma anche di accedere alla posizione del valore e accedere ai valori di tutto il resto del negozio. In altre parole, extend utilizza il valore e il contesto circostante per eseguire l'aggiornamento.

Un'analogia più computerizzata sarebbe quella di pensare a un Store come un grande piatto di un disco rigido con valori memorizzati in varie posizioni, oltre a una testa parcheggiata in una particolare posizione.

Problemi correlati