?

Log in

No account? Create an account
Дно двунаправленности пробито - Дважды мудак [entries|archive|friends|userinfo]
Декларативное рулит

Site Meter

[ website | Мой сайт ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Дно двунаправленности пробито [окт. 10, 2017|22:06 pm]
Andy Melnikov
[Tags|, , , ]

import System.IO.Streams (contramap)
quux x = do
   foo <- contramap show x
   bar <- contramap Just foo
   return bar
Все мы помним State-монаду, в которой состояние движется в другую сторону и взбирается по ду-нотации вверх. Сегодня я столкнулся с продвижением контрол-флоу против стрелок обычной монады IO.

Т.е. у нас "вход" как бы снизу, а x - это "выход". return bar отправляет этот вход в bar, дальше он проходит Just и отправляется в foo, а оттуда проходит через show и попадает в x

Тип соответствующий:
quux :: Show a => OutputStream String -> IO (OutputStream a)
a "на входе", затем Just делает Maybe a, и show делает строку.
СсылкаОтветить

Comments:
[User Picture]From: avnik
2017-10-11 10:16 am
Но как???
(Ответить) (Thread)
From: (Anonymous)
2017-10-11 11:28 am
Монада вещь абстрактная и, вопреки примерам с IO, не обязана ничего исполнять по порядку. Я так подозреваю, что тут работает монада, которая запоминает операции и применяет их наоборот, в стиле https://hackage.haskell.org/package/tardis-0.4.1.0/docs/Control-Monad-Tardis.html .
(Ответить) (Parent) (Thread)
[User Picture]From: nponeccop
2017-10-11 11:59 pm
В этом топике везде монада IO стандартная :)
(Ответить) (Parent) (Thread)
[User Picture]From: nponeccop
2017-10-11 10:17 pm
Обратный контрол флоу просто объяснить примером:

push a l = return $ a : l

main =
    return [] >>=
    push (print "1") >>=
    push (print "2") >>=
    sequence_
Теперь если насоздавать синонимов, получаем:

main =
    stop >>=
    exec (print "1") >>=
    exec (print "2") >>=
    start
Этот код надо читать снизу вверх, поскольку логически у нас
start;
print "2";
print "1";
stop;
(Ответить) (Parent) (Thread)
[User Picture]From: nponeccop
2017-10-11 11:29 pm

Гетерогенный список c >=> вместо (:)

Используя сабж, можно захуячить такоэ:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Monad ((>=>))

op1 = const getLine
op2 = return . read
op3 = return . (+(42000::Int))
op4 = print

run = exec op4 >=> exec op3 >=> exec op2 >=> exec op1

main = stop >>= run >>= start

start = return return
exec a l = return $ a >=> l
stop f = f ()
Идейно это то же самое, что предыдущий пример. Но теперь мы против стрелки можем передавать и данные!

Вот чуть более упоротое решение, адаптированное для >>= в исходном коде вместо >=>:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Monad ((>=>))

op1 = getLine
op2 = return . read
op3 = return . (+(42000::Int))
op4 = print

main = stop op4 >>= exec op3 >>= exec op2 >>= start op1

-- эквивалентно
main' = op1 >>= op2 >>= op3 >>= op4

exec op l = return $ op >=> l
stop = return
start op l = return (const op >=> l) >>= ($ ())



Edited at 2017-10-12 00:04 (UTC)
(Ответить) (Parent) (Thread)