Comments (6)
test_sequence() ->
List = lists:seq(1,5),
ListM = [do([maybe_m || return(io:format("~p~n", [N])),
return(N)]) || N <- List],
{just, List} = monad:sequence(maybe_m, ListM).
does indeed print out the numbers 1 to 5, in that order.
sequence
is a pretty direct translation of the Haskell version at http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Monad.html#sequence
That too, uses foldr
. Whilst the list is indeed traversed from right to left, don't forget that you're actually the evaluation as part of the list construction, and that is done left to right. It is only the combination of the results that is done by sequence
. So for example:
test_sequence() ->
List = lists:seq(1,5),
ListM = [do([maybe_m || return(io:format("~p~n", [N])),
return(N)]) || N <- List],
io:format("HERE~n"),
{just, List} = monad:sequence(maybe_m, ListM).
here, you get the numbers printed out first, then HERE
. Does that make sense?
from erlando.
There is an interesting issue though with more complex monads where "values" are actually functions. For example, compare the difference between:
test_sequence() ->
StateT = state_t:new(identity_m),
List = lists:seq(1,5),
ListM = [do([StateT || return(io:format("~p~n", [N])),
return(N)]) || N <- List],
io:format("HERE: ~p~n", [ListM]),
io:format("~p~n", [StateT:run(monad:sequence(StateT, ListM), undefined)]).
and
test_sequence() ->
StateT = state_t:new(identity_m),
List = lists:seq(1,5),
ListM = [do([StateT || return(true),
return(io:format("~p~n", [N])),
return(N)]) || N <- List],
io:format("HERE: ~p~n", [ListM]),
io:format("~p~n", [StateT:run(monad:sequence(StateT, ListM), undefined)]).
In the do
transform, the construction of the list will actually force the evaluation of the argument to the first return
. So even though in both cases, ListM
will be a list of functions, in the first example, you'll get the numbers printed out before the HERE
, but not in the second case.
In the first case, as the io:format
is performed as part of list construction, it's easy to see it happens left to right. In the second case, it occurs only as a result of the StateT:run
call. Whilst sequence
does iterate right-to-left through the list, don't forget the list is a list of functions, and thus sequence
itself must return a function too - itself, it is not really doing any work at all. So if you then look at the nature of the function that sequence
will return, you'll see that the "current" value is forced before the accumulator: ultimately you'll end up with a series of nested functions, one per list element, and the outer-most will correspond to the first element of the list (and was constructed last, due to the use of foldr
). It is then only when you hit the StateT:run
(or eval
or exec
) that the outer-most function will be invoked, and evaluation will the ripple down.
from erlando.
I'm just curious about the monad:sequence/2's order of evaluation for monads with side effects like below.
it looks like evaluating right to left.
And I also believe haskell's sequence evaluates left to right as written in the document ---
"...Evaluate each action in the sequence from left to right, and collect the results... ".
Yes, haskell's sequence is also using foldr, but it is not strict. Their foldr is just right associative
and it does not affect the order of evaluation.
% cat src/seffect_m.erl
-module(seffect_m).
-compile({parse_transform, do}).
-behaviour(monad).
-export(['>>='/2, return/1, fail/1,
test_do/0, test_seq/0]).
'>>='(X, Fun) ->
io:format(":::~p:::~n", [X]),
Fun(X).
return(X) -> X.
fail(X) -> throw({error, X}).
%% --- test ---
test_do() ->
M0 = abc,
M1 = def,
do([seffect_m || V0 <- M0, V1 <- M1, return([V0, V1])]).
test_seq() ->
M0 = abc,
M1 = def,
monad:sequence(seffect_m, [M0, M1]).
% erl -pz ./ebin
Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8.2 (abort with ^G)
1> seffect_m:test_do().
:::abc:::
:::def:::
[abc,def]
2> seffect_m:test_seq().
:::def:::
:::[]:::
:::abc:::
:::[def]:::
[abc,def]
3>
from erlando.
I think this is fixed in the above commit - certainly my testing and thinking supports this. I'm quite pleased that the implementation I've come up with is both tail-call based and does not use ++
. Please let me know if this works for you.
from erlando.
Mmm, I wonder if the same issue occurs in monad_plus:msum, and maybe also the "real" implementation of >>=
in list_m.
from erlando.
I repeated the same small example in my comment above. Yes, it is now left to right. Thanks.
% erl -pz e bin
Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8.2 (abort with ^G)
1> seffect_m:test_seq().
:::abc:::
:::def:::
[abc,def]
2>
from erlando.
Related Issues (11)
- eunit test run does not detect test failures HOT 1
- R16B support HOT 7
- Can't run make HOT 1
- use of parameterized modules? HOT 3
- Time to tag new release? HOT 4
- Publish to hex.pm HOT 1
- The syntax of cuts HOT 17
- parameterized modules are no longer supported HOT 1
- Haskell in Erlang? HOT 1
- Unused variable compiler warnings HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from erlando.