В настоящее время я изучаю бесплатные монады, и я играл, наверное, с самым простым и распространенным примером - Teletype
:
{-# LANGUAGE DeriveFunctor #-}
import Control.Monad.Free
data TeletypeF a = Put String a
| Get (String -> a)
deriving Functor
type Teletype = Free TeletypeF
Многие учебные пособия интерпретируют Teletype
программы в IO
монада.Например:
-- Utilities
get = liftF $ Get id
put s = liftF $ Put s ()
-- Sample programs
echo :: Teletype ()
echo = do word <- get
if word == "\04" -- Ctrl-D
then return ()
else put word >> echo
hello :: Teletype ()
hello = do put "What is your name?"
name <- get
put "What is your age?"
age <- get
put ("Hello, " ++ name ++ "!")
put ("You are " ++ age ++ " years old!")
-- Interpret to IO
interpIO :: Teletype a -> IO a
interpIO = foldFree lift
where
lift (Put s a) = putStrLn s >> return a
lift (Get f) = getLine >>= return . f
Я пытался интерпретировать это в другой монаде, а именно в монаде RWS .Эта идея была мотивирована последним упражнением из этого задания .Я использую тип данных RWS
для извлечения входных данных из части Reader
и накопления выходных данных в части State
.Но, к сожалению, я не могу заставить его работать.Вот моя попытка:
import Control.Monad.Trans.RWS.Lazy hiding (get, put)
type TeletypeRWS = RWS [String] () [String]
-- Interpret to TeletypeRWS
interpRWS :: Teletype a -> TeletypeRWS a
interpRWS = foldFree lift
where
lift (Put s a) = state (\t -> ((), t ++ [s])) >> return a
lift (Get f) = reader head >>= local tail . return . f -- This is wrong
mockConsole :: Teletype a -> [String] -> (a, [String])
mockConsole p inp = (a, s)
where
(a, s, _) = runRWS (interpRWS p) inp []
При запуске TeletypeRWS
«программ» первое значение в окружении не удаляется:
*Main> mockConsole hello ["john", "18"]
((),["What is your name?","What is your age?","Hello, john!","You are john years old!"])
Я немного обеспокоеноб обновлении Reader
, но я не знаю, как еще я могу получить доступ к следующему значению в списке.Тип TeletypeRWS
был выбран на основе вышеупомянутого упражнения, поэтому я предполагаю, что должна быть возможность реализовать interpRWS
.