W trakcie pisania zadania na uniwersytet mam radość z uczenia się nowych monad Haskella. Yay !!!Rozpakowywanie monady stanu Haskell
Mam funkcję, która typechecks dobrze:
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
ale gdy ta inna funkcja:
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)
próbuje je nazwać, to wysadza na linii
s1 <- compile prog
mówiąc, że nie może on być zgodny z oczekiwanym typem "IO t0" z faktycznym typem "State VarsState String".
Zakładam, że to dlatego, że may_compile_prog zwraca typ IO(), więc spodziewa się tylko rozwinąć informacje o IO? VarsState jest niestandardowym typem danych, którego użyłem z Monadą państwową/
Jednakże, jeśli to jest problem i zakładam, że jest, nie wiem jak przekazać ten prosty ciąg do may_compile_prog. Naprawdę, to wszystko, co chcę zrobić - nadać ciągowi may_compile_prog.
Być może jest jakiś schludny sposób na rozwinięcie tej monady stanu? Być może możliwe jest przepisanie "kompilacji" tak, aby pobierać informacje o monadach stanu podczas działania, ale po prostu zwraca ciąg (nie zawinięty w żadną monadę)?
Proszę dać mi znać, jeśli brakuje mi jakichkolwiek informacji.
Idealny gość. Z wyjątkiem jednej małej rzeczy, kompiluje się z "let s1 = evalState (compile prog) initialState", a nie "let s1 = evalState $ compile prog initialState". Jeszcze jedno pytanie - czy istnieją takie funkcje dla innych monad? tj. funkcje, które odwijają monadę i zwracają tylko wynik? – nebffa
@nebffa zależy całkowicie od monady, ale tak, niektóre z nich tak.To nie jest coś, co możesz zrobić ogólnie dla wszystkich monad. Innym przykładem może być przerażający 'unsafePerformIO' dla monada' IO', ale nie powinieneś tego używać. –
Ach, tak, pomieszałem nawiasy (najpierw zapomniałem o stanie, a potem zapomniałem wymienić '$' podczas dodawania). Dzięki za heads-up. Dla wielu monad istnieją odpowiednie funkcje, ale nie dla wszystkich. 'IO' to taki, w którym nie ma takiego [no cóż, jest taki, którego nazwa zaczyna się od' unsafe' i naprawdę to naprawdę oznacza]. Istnieją 'runIdentity',' runReader', 'runWriter',' runCont', ... Spójrz na dokumenty dla każdej monady, czy istnieją takie funkcje. –