|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[18] £ сс Order is important when combining monads. StateTs (Error e) is different than ErrorTe (State s). The first produces a combined type of s -> Error e (a,s), in which the computation can either return a new state or generate an error. The second combination produces a combined type of s -> (Error e a,s), in which the computation always returns a new state, and the value can be an error or a normal value. 3.5. Anatomy of a monad transformer In this section, we will take a detailed look at the implementation of one of the more interesting transformers in the standard library, StateT. Studying this transformer will build insight into the transformer mechanism that you can call upon when using monad transformers in your code. You might want to review the section on the State monad before continuing. 3.5.1. Combined monad definition Just as the State monad was built upon the definition newtype State s a = State { runState :: (s -> (a,s)) } the StateT transformer is built upon the definition newtype StateT s m a = StateT { runStateT :: (s -> m (a,s)) } State s is an instance of both the Monad class and the MonadState s class, so StateTs m should also be members of the Monad and MonadState s classes. Furthermore, if m is an instance of MonadPlus, StateTs m should also be a member of MonadPlus. To define StateT s m as a Monad instance: newtype StateT s m a = StateT { runStateT :: (s -> m (a,s)) } instance (Monad m) => Monad (StateT s m) where return a= StateT $ \s -> return (a,s) (StateT x) >>= f = StateT $ \s -> do (v,s)<- x s- get new value, state (StateT x) <- return $ f v - apply bound function to get new state transformation fn apply the state transformation fn to the new state Compare this to the definition for State s. Our definition of return makes use of the return function of the inner monad, and the binding operator uses a do-block to perform a computation in the inner monad. We also want to declare all combined monads that use the StateT transformer to be instaces of the MonadState class, so we will have to give definitions for get and put: instance (Monad m) => MonadState s (StateT s m) where
get = StateT $ \s -> return (s,s) put s = StateT $ \ -> return ((),s) Finally, we want to declare all combined monads in which StateT is used with an instance of MonadPlus to be instances of MonadPlus: instance (MonadPlus m) => MonadPlus (StateT s m) where mzero = StateT $ \s -> mzero (StateT xl) "mplus" (StateT x2) = StateT $ \s -> (xl s) "mplus" (x2 s) 3.5.2.Defining the lifting function The final step to make our monad transformer fully integrated with Haskells monad classes is to make StateTs an instance of the MonadTrans class by providing a lift function: instance MonadTrans (StateT s) where lift c = StateT $ \s -> c >>= (\x -> return (x,s)) The lift function creates a StateT state transformation function that binds the computation in the inner monad to a function that packages the result with the input state. The result is that a function that returns a list (i.e., a computation in the List monad) can be lifted into StateT s [], where it becomes a function that returns a StateT (s -> [(a,s)]). That is, the lifted computation produces multiple (value,state) pairs from its input state. The effect of this is to "fork" the computation in StateT, creating a different branch of the computation for each value in the list returned by the lifted function. Of course, applying StateT to a different monad will produce different semantics for the lift function. 3.5.3.Functors We have examined the implementation of one monad transformer above, and it was stated earlier that there was no magic formula to produce transformer versions of monads. Each transformers implementation will depend on the nature of the computational effects it is adding to the inner monad. Despite this, there is some theoretical foundation to the theory of monad transformers. Certain transformers can be grouped according to how they use the inner monad, and the transformers within each group can be derived using monadic functions and functors. Functors, roughly, are types which support a mapping operation fmap :: (a->b) -> f a -> f b. To learn more about it, check out Mark Jones influential paper that inspired the Haskell monad template library. 3.6. More examples with monad transformers At this point, you should know everything you need to begin using monads and monad transformers in your programs. The best way to build proficiency is to work on actual code. As
your monadic programs become more abitious, you may find it awkward to mix additional transformers into your combined monads. This will be addressed in the next section, but first you should master the basic process of applying a single transformer to a base monad. 3.6.1. WriterT with IO Try adapting the firewall simulator of example 17 to include a timestamp on each log entry (dont worry about merging entries). The necessary changes should look something like this: Code available in example22.hs -- this is the format of our log entries data Entry = Log {timestamp::ClockTime, msg::String} deriving Eq instance Show Entry where show (Log t s) = (show t) ++ -- this is the combined monad type type LogWriter a = WriterT [Entry] IO a -- add a message to the log logMsg :: String -> LogWriter () logMsg s = do t <- liftIO getClockTime tell [Log t s] -- this handles one packet filterOne :: [Rule] -> Packet -> LogWriter (Maybe Packet) filterOne rules packet = do rule <- return (match rules packet) case rule of Nothing -> do logMsg ("DROPPING UNMATCHED PACKET: " ++ (show packet)) return Nothing (Just r) -> do when (logIt r) (logMsg ("MATCH: " ++ (show r) ++ " <=> " ++ (show packet))) case r of (Rule Accept ) -> return (Just packet) (Rule Reject ) -> return Nothing -- this filters a list of packets, producing a filtered packet list -- and a log of the activity filterAll :: [Rule] -> [Packet] -> LogWriter [Packet] filterAll rules packets = do logMsg "STARTING PACKET FILTER" out <- mapM (filterOne rules) packets logMsg "STOPPING PACKET FILTER" return (catMaybes out)
|
Среды: Smalltalk80 MicroCap Local bus Bios Pci 12С ML Микроконтроллеры: Atmel Intel Holtek AVR MSP430 Microchip Книги: Емкостный датчик 500 схем для радиолюбителей часть 2 (4) Структура компьютерных программ Автоматическая коммутация Кондиционирование и вентиляция Ошибки при монтаже Схемы звуковоспроизведения Дроссели для питания Блоки питания Детекторы перемещения Теория электропривода Адаптивное управление Измерение параметров Печатная плата pcad pcb Физика цвета Управлении софтверными проектами Математический аппарат Битовые строки Микроконтроллер nios Команды управления выполнением программы Перехода от ahdl к vhdl Холодный спай Усилители hi-fi Электронные часы Сердечники из распылённого железа Анализ алгоритмов 8-разрядные КМОП Классификация МПК История Устройства автоматики Системы и сети Частотность Справочник микросхем Вторичного электропитания Типы видеомониторов Радиобиблиотека Электронные системы Бесконтекстный язык Управление техническими системами Монтаж печатных плат Работа с коммуникациями Создание библиотечного компонента Нейрокомпьютерная техника Parser Пи-регулятор ч.1 ПИ-регулятор ч.2 Обработка списков Интегральные схемы Шина ISAВ Шина PCI Прикладная криптография Нетематическое: Взрывной автогидролиз Нечеткая логика Бытовые установки (укр) Автоматизация проектирования Сбор и защита Дискретная математика Kb радиостанция Энергетика Ретро: Прием в автомобиле Управление шаговым двигателем Магнитная запись Ремонт микроволновки Дискретные системы часть 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||