Nel processo di scrittura di un incarico per l'università mi sto divertendo sempre di più ad imparare nuove monadi Haskell. Sìì!!!Unwrapping the Haskell State Monad
Ho una funzione che typechecks bene:
compile :: Prog -> State VarsState String
compile [email protected](Prog functions) = do
s1 <- sequence (map (translate_func 0) [get_function prog name | name <- [func_name func | func <- functions]])
return $ trace ("here's the program: \n" ++ show prog) $ concat $ s1
ma quando questa altra funzione:
maybe_compile_prog ::
MaybeOK Prog -> String -> IO()
maybe_compile_prog (Error msg) _ = do
putStrLn ("error: " ++ msg)
maybe_compile_prog (OK prog) modulename = do
s1 <- compile prog
writeFile (modulename ++ ".m") ((header modulename) ++ s1)
tenta di chiamare esso, fa saltare in aria alla linea
s1 <- compile prog
dicendo che non potrebbe corrispondere al tipo previsto "IO t0" con tipo effettivo "State VarsState String".
Presumo che ciò è dovuto al fatto rendimenti maybe_compile_prog tipo IO() in modo che si aspetta di solo unwrap informazioni IO? VarsState è un tipo di dati personalizzato che ho fatto da usare con la monade Stato/
Tuttavia, se questo è il problema e suppongo che sia, non so come trasmettere questa semplice stringa maybe_compile_prog. Davvero, questo è tutto ciò che voglio fare - dare una stringa a forse_compile_prog.
Forse c'è un modo pulito per scartare questa monade di stato? Forse è possibile riscrivere "compile" in modo da contenere alcune informazioni di monade di stato mentre viene eseguito, ma poi restituisce semplicemente una stringa (non racchiusa in nessuna monade)?
Per favore fatemi sapere se mi mancano informazioni.
Tizio perfetto. Tranne che per una piccola cosa, esso viene compilato con "let s1 = evalState (prog prog)", non "let s1 = evalState $ compilare prog initialState". Un'altra domanda: ci sono funzioni come questa per altre monadi? cioè funzioni che scartano la monade e ti restituiscono solo il risultato? – nebffa
@nebffa dipende interamente dalla monade in questione, ma sì, alcuni di loro lo fanno.Non è qualcosa che puoi fare genericamente per tutte le monadi. Un altro esempio potrebbe essere il temuto 'unsafePerformIO' per la monade' IO', ma non dovresti usarlo. –
Ah, sì, ho mescolato le parentesi (ho dimenticato prima lo stato e poi ho dimenticato di scambiare il '$' quando lo aggiungi). Grazie per il testa a testa. Per molte monadi ci sono funzioni corrispondenti, ma non per tutte. "IO" è uno dove non ce n'è uno [beh, ce n'è uno il cui nome inizia con "non sicuro" e in realtà lo significa davvero]. Ci sono 'runIdentity',' runReader', 'runWriter',' runCont', ... Guarda i documenti per ogni monade se ci sono tali funzioni. –