Erlang

библиотека erlmonads

Введение

do-нотация

Программная запятая через parse_transform

do([Monad ||
    A <- foo(),
    B <- bar(A, dog),
    B
]).
Monad:'>>='(
    foo(),
    fun (A) -> Monad:'>>='(
        bar(A, dog),
        fun (B) -> B end)
    end).

do-нотация (Haskell)

    
    do
        a <- foo
        b <- bar a dog
    
    
    foo >>= \a ->
        bar a dog >>= \b -> b
    

Maybe

return(X) -> {just, X}.
fail(_X)  -> nothing.

do([erlmonads_maybe ||
    Num <- get_number(),
    erlmonads_plus:guard(erlmonads_maybe, is_number(Num)),
    processing_number(Num),
    return(Num)
])

Error

Варианты обработки ошибов

Error

ErrGuard = erlmonads_plus:guard(erlmonads_error, _, _),

Res = do([erlmonads_error||
    Connection <- amqp_connection:start(AMQP_params),
    Channel <- amqp_connection:open_channel(Connection),
    ConnectionRef <- return(erlang:monitor(process, Connection)),
    ChannelRef <- return(erlang:monitor(process, Channel)),
    ErrGuard(
        'exchange.declare_ok' =:= element(1, amqp_channel:call(Channel, EDeclareCmd)),
        "Could not declare exchange"),
    ErrGuard(
        'queue.declare_ok' =:= element(1, amqp_channel:call(Channel, QDeclareCmd)),
        "Could not declare queue"),
    ErrGuard(
        'queue.bind_ok' =:= element(1, amqp_channel:call(Channel, BindCmd)),
        "Could not bind queue to exchange"),
    ErrGuard(
        'basic.consume_ok' =:= element(1, amqp_channel:call(Channel, ConsumeCmd)),
        "Could not consume"),
    return(#state{
            connection=Connection,
            channel=Channel,
            connection_ref=ConnectionRef,
            channel_ref=ChannelRef}
)]),

State монада

Пример реализации вычисления факториала

fact_rec(0) ->
    do([erlmonads_state ||
        Acc <- get(),
        return(Acc)
    ]);
fact_rec(N) ->
    do([erlmonads_state ||
        Acc <- get(),
        put(Acc * N),
        fact_rec(N - 1)
    ]).

fact(N) ->
    erlmonads_state:eval(
        fact_rec(N),
        1
    ).

State монада (Haskell)

Пример реализации вычисления факториала

fact_rec :: Int -> State Int Int
fact_rec 0 = do
    acc <- get
    return acc
fact_rec n = do
    acc <- get
    put (acc * n)
    fact_rec (n - 1)

State монада

Пример реализации вычисления чисел фибоначчи

-import(erlmonads_state, [
    eval/2, modify/1,
    sequence/1, exec/2
]).

fib_m_step() ->
    modify(fun ({X, Y}) -> {Y, X+Y} end).

fib(N) ->
    {A, _} = exec(
        sequence(
            lists:duplicate(N, fib_m_step())
        ),
        {0, 1}
    ),
    A.

State монада (Haskell)

Пример реализации вычисления чисел фибоначчи

fib_m_step :: State (Int, Int) ()
fib_m_step = 
    modify $ \(a,b) -> (b,a+b)

fib :: Int -> Int
fib n = fst ((execState $ 
        sequence (Data.List.replicate n fib_m_step)
    )
    (0, 1))

Трансформеры



Реализация State-монады через трансформер

State = erlmonads_state_t:new(erlmonads_identity)

Ссылки