Come esercizio di apprendimento, sto cercando di implementare un heapsort in Haskell. Ho pensato che la monade State
sarebbe stata la scelta giusta per fare questo, dal momento che gli heap si basano abbastanza sul trasferimento dei dati all'interno di una singola struttura (e la notazione do
sarebbe utile). Inoltre, sto cercando di consolidare la mia comprensione delle monadi in generale.L'API Control.Monad.State è stata modificata di recente?
Il examples on the State
monad in impari A Haskell (e un number di othertutorials), dicono che State
è definito come:
newtype State s a = State { runState :: s -> (a,s) }
dovrei essere di passaggio in funzione del tipo di s -> (a,s)
(che può essere o non essere curried in altri argomenti) al costruttore del valore State
. Quindi le mie funzioni simile a questa:
pop :: Ord a => State (Heap a) a
pop = State pop'
pop' :: Ord a => Heap a -> (a, Heap a)
-- implementation of pop' goes here
push :: Ord a => a -> State (Heap a)()
push item = State $ push' item
push' :: Ord a => a -> Heap a -> ((), Heap a)
-- implementation of push' goes here
Questo non viene compilato, con il seguente errore:
Not in scope: data constructor `State'
Perhaps you meant `StateT' (imported from Control.Monad.State)
Dalla lettura del API docs per Control.Monad.State
, sembra che il costruttore State
valore è stato rimosso dal modulo poiché sono stati scritti questi tutorial. Come principiante, trovo che la documentazione sia lungi dall'essere autoesplicativa. Quindi la mia domanda è:
- Ho ragione nel ritenere che il costruttore del valore
State
sia sparito? - Cosa dovrei usare invece?
è 'state' una sostituzione drop-in per' State'? O devo dichiarare un'istanza di 'MonadState' per la mia struttura dati prima che funzioni? –
'state' è un rimpiazzo sostitutivo per' State' mentre lo stai usando, sì. 'State (Heap a)' è ciò che deve essere un'istanza di 'MonadState', e lo è già. – dave4420
Qual è lo stile consigliato per il tuo suggerimento di usare la notazione 'do' con' get' e 'put'? Dovrei definire la maggior parte delle mie funzioni di basso livello non monadicamente (per esempio: 'push :: Ord a => a -> Heap a -> Heap a'), e quindi costruisci un calcolo statico di questi in un' do 'Blocca usando un sacco di legami' let'? O dovremmo 'push' e' pop' (o, a un livello inferiore, le mie routine tree-traversal) essere funzioni monadiche che possono essere sequenziate direttamente in un blocco 'do'? –