►
From YouTube: Introduction to Async ADTs - Tom Wilson
Description
In this demo, we talk about the inside semantics of the Async ADT, how it wraps functions and passes the functions around as values to create a pure environment that does not invoke side effects until the fork method is called.
For more information about Async ADTs check out the companion blog post - https://blog.hyper.io/introduction-to-async-adt/
A
This
is
a
super
confusing
subject
and
if
you're
not
familiar
with
a
little
bit
of
functional
programming
more
than
likely,
this
is
probably
going
to
confuse
you
a
lot,
but
I'm
going
to
try
to
keep
it
simple
and
try
to
go
through
it.
I
do
have
a
previous
demo
on
just
understanding.
Adts
in
general,
adts
are
algebraic
data
types,
and
I
recommend
you
watch
that
video
before
watching
this
video,
so
that
you
get
an
idea
of
kind
of
the
pattern
with
adts.
A
We
want
to
create
highly
maintainable
extendable,
reliable
software.
There's
several
ways
to
go
about
doing
this.
Adts
is
one
that
can
greatly
simplify
the
process
and
just
create
very
easy
to
follow
guard
rails
to
kind
of
keep
you
from
injecting
kind
of
side
effects
in
your
business
logic.
There's
other
ways
to
do
that.
Like
patterns
like
flux,
architecture,
for
example,
but
one
of
the
challenges
with
that
is
kind
of
the
way
it
spreads
kind
of
your
business
logic
and
action
creators
and
then
reducers
and
selectors.
A
A
We
actually
created
an
a
very
simple
adt
called
id
and
id
takes
a
value,
and
then
it
returns
a
kind
of
container,
and
this
container
has
a
map
function
and
that
map
function
takes
a
function
as
an
argument,
and
then
it
returns
a
it
replaces
the
value
in
the
container,
by
returning
a
new
container
and
running
that
function
on
that
to
get
the
new
value
and
then
a
chain
takes
a
function
and
it
just
returns
the
result
of
that
function,
because
that's
going
to
be
a
new
container
right.
The
chain
works
like
a
flat
map.
A
A
So
that's
our
you
know
very
simple
adt
and
we
can
work
with
that
by
running.
You
know
by
instantiating
the
a
d
t,
let's
say
with
a
value
of
one
and
then
mapping
over
that
and
adding
a
value
to
that
and
then
chaining
with
that
and
again,
we've
got
to
return
a
new
adt,
our
id
so
we'll
just
say
value
plus
two
right
and
that
returns
a
new
one
and
then
we'll
do
an
extract.
A
Out
it's
great,
so
that's
a
very
simple
adt,
but
let's
look
at
side
effects
like
you
know,
promises
or
fetches,
or
any
kind
of
call
that
actually
does
something
to
the
outside
world.
A
So,
let's
see
how
that
that
looks
so
a
common
procedure
for
this
kind
of
wrapper
function
is
a
function,
signature
that
takes
a
rejected
function
and
a
resolved
function
as
arguments,
and
then
it
will
either
call
rejected
or
resolved
based
on
some
value.
So
so,
for
starters,
let's
just
say,
resolved
hello
right
and
that's
our
kind
of
function
that
we
want
to
add
to
the
array
or
the
container
as
a
value.
A
So
we
can
just
start
with
the
container
and
we
can
just
put
the
function
in
the
container
and
then
we
want
to
kind
of
get
the
function
out
and
then
run
run,
run
the
function
right
run,
each
of
the
rejected
and
the
resolve,
functions
or
or
call
the
function,
passing
it
and
a
rejected
and
resolved
function.
A
A
No
comma
here
there
we
go
so
we
got
a
solution
and
it
returned
hello.
Now
this
is
very
contrived
and-
and
you
know
basically
we're
just
saying
x-
equals
function
here,
but
let's
add
a
map
right.
So
what
if
we
wanted
to
map
over
a
function?
What
would
that
look
like?
A
Well
when
map
is
called
it's
going
to
give
us
the
value
and
that
value
is
a
function
right
and
what
we're
going
to
want
to
do
is
we're
going
to
want
to
return
another
function
that
meets
that
signature
right,
so
we're
going
to
want
to
return
a
function
that
takes
a
rejected
and
a
resolved,
and
then
inside.
That
is
where
we
can
actually
do
some
work,
so
we
can
call
resolved.
A
All
right,
because
we
want
this
to
be
a
a
successful
result,
we
could
call
rejected
if
we
wanted
it
to
to
reject
or
become
a
rejected
kind
of
state,
but
we're
going
to
call
resolved
and
when
we
call
resolved,
we
need
to
give
it
a
result
and
we're
going
to
use
the
function.
A
That
is
the
value
passed
in
and
we're
going
to
call
it
and
for
rejected
we're
just
going
to
create
an
identity
function
and
for
resolved
we're
going
to
pass
in
a
function
that
takes
the
value
and
then
increments
the
value
or
concatenates
it
with
the
string
space
world
right
and
then
we'll
close.
That
up,
which
I
think
we
have
here
just
have
to
add
one
more
there.
A
So
now
we're
going
to
take
this
function
as
a
value
put
it
in
a
container,
then
map
over
it
and
return
a
new
function
which
will
replace
that
value.
Just
like
we
did
a
1
and
a
1
plus
1
2
replaces
that
it's
going
to
replace
that
function
with
this
function,
which
is
going
to
resolve
it.
So,
at
the
end
of
the
day,
we
should
log
out
hello
world
if
everything
works
right.
A
A
But
we
want
to
kind
of
remove
some
of
this
boilerplate
right
because
it
would
just
be
super
painful
having
to
to
do
that
all
the
time
and
it's
pretty
easy
to
remove.
So,
let's
do
that,
let's,
let's
remove
some
of
that
boiler
plate
and
create
a
a
sync
adt.
A
So
we've
got
sync
and
we're
going
to
take
that
function
and
we're
just
going
to
call
it
fork
because
we
actually
call
the
fort
function,
and
that
is
the
signature.
It
takes
a
rejected
and
a
resolved,
and
then
it
either
is
going
to
call
the
rejected
or
call
the
resolved
when
it
runs
and-
and
that
gives
us
this
way-
to
wrap
kind
of
side
effects.
A
A
Okay,
and
that's
all
we're
going
to
have
for
this
simple
type
and
we
can
add
more
functionality
to
these
and
we'll
just
show
that
in
a
little
bit.
But
let's,
let's
just
stick
with
map
and
chain
for
now.
Okay.
A
So
when
we
did
map
with
the
id
function,
we
really
just
basically
took
the
function
and
then
we
took
the
type
in
this
case
a
sink.
And
then
we
ran
the
function
with
the
value
right.
A
A
Once
it's
passed
to
us,
so
we're
going
to
create
a
rejected,
resolved
or
fork
kind
of
function,
and
then
we're
going
to
call
fork
right.
We're
going
to
call
the
value
and
pass
in
the
rejected
function,
that's
passed
into
us
and
then
for
the
resolved,
we're
going
to
pass
in
this
function.
That
will
give
us
the
value
and
then
we're
going
to
call.
A
Okay,
so
that
is
kind
of
super
complicated,
but
basically
what
we're
doing
is
if
it's
rejected.
We
just
continue
down
the
chain,
so
that'll
kind
of
escape
out.
If
it's
resolved,
we
actually
want
to
invoke
the
functionality
by
calling
the
function
that's
being
passed
in
with
the
the
value,
that's
kind
of
wrapped
inside
the
the
other
function
and
then
resolve
it,
and
that
allows
us
to
when,
when
we're
actually
coding
to
code
as
if
we're
working
with
values
that
have
not
been
called
yet
and
that's
pretty
crazy,
but
it
works.
A
So
I'm
going
to
comment
out
chain,
because
I
think
that
I
will
confuse
myself
trying
to
explain
chain
right
now,
but
I
do
want
to
create
a
helper
function,
a
sync
dot
of
which
will
take
a
value
and
basically,
what
we're
going
to
do
is
return
in
a
sync
and-
and
this
is
kind
of
going
to
just
inject
this
value
or
wrap
it
in
a
function
right
in
the
sync
function.
A
So
I'm
going
to
do
rejected,
resolved
and
then
we're
going
to
say,
resolved
v
and
this
kind
of
works
like
a
constructor,
so
that
we
can
just
sort
of
start
with
a
value
and
then
we
can
map
over
it
and
then
fork
it
and
you'll
kind
of
see
what
happens
there.
So
if
we
do
async.up
with
the
value
and
then
we
map
the
value-
and
we
can
just
now
just
like
we
did
with
the
identity
function,
we
can
just
do
value
plus
two
and
then
the
difference
is
we're
not
going
to
run.
A
A
A
A
And
with
rejected,
we
just
pass
go,
collect,
200
and
with
resolved
we
take
the
the
value
we
call
it
on
the
function
which
should
return
us
another,
a
sink
right
when
we
call
that
function.
It'll
return
us
in
the
sync
container,
so
then
we're
going
to
call
fork
on
it
and
then
we're
going
to
pass,
rejected
and
resolved,
and
that
gives
us
a
chain
or
a
flat
map
in
this
async
component,
which
is
pretty
cool.
A
So
if
I
do
a
chain
and
take
the
value
which
will
now
be
three
and
then
return
a
new
async
and,
let's
say
42,
just
like
the
identifier,
the
id
80t,
it
should
just
replace
the
value
with
42
and
it
does
sweet.
So
now
we've
got
this
adt.
That
follows
the
same
kind
of
pattern
that
the
id
adt
does,
but
we're
actually
wrapping
functions,
so
those
functions
can
actually
wrap
side
effects.
A
Let's
look
at
an
example,
so
a
common
example
is
a
promise.
A
promise
is
a
function
that
will
most
likely
result
in
side
effects.
We
can
actually
wrap
that
by
using
a
helper
method.
A
A
A
It
could
be
a
fetch,
it
could
be
any
other
kind
of
async
function
that
would
go
out
and
do
something
so
it
doesn't
get
called
until
we
call
fork,
but
we
can
treat
it
as
if
it
did
get
called
so
we
could
treat
it
as
it
as
if
it
did,
which
would
return
a
value
of
one
and
then
we
can
add
two
to
it
and
then
we
can
replace
it
as
well.
So,
let's
see
if
this
works.
A
I
know
that
that
is
a
lot
to
think
about
and
a
lot
to
get
your
head
around.
The
big
reason
why
we
want
to
do
this
is
so
that
we
can
separate
our
side
effects
or
actions
from
our
pure
business
logic.
So
we
can
do
map
chain
map
chain
on
all
of
our
business
logic,
using
very
simple,
pure
functions,
and
then,
when
we're
ready
to
execute
those
side
effects,
we
just
call
fork,
and
it
just
keeps
everything-
nice
and
clean
and
easy
to
reason
about.
A
So,
hopefully
that
helps
I'm
going
to
post
some
notes
in
the
description,
and
hopefully
you
know
you
start
using
these
async
adts
I'll
guarantee
you.
If
you
take
the
time
to
learn
this
and
wrap
promises
and
other
side
effects
in
this,
you
will
have
much
cleaner
code
easier
to
debug
and
you'll
be
happy
because
you
won't
be
fighting
these
kind
of
problems
that
can
kind
of
come
out
of
nowhere.
So,
thank
you
for
your
time.
I
hope
you
have
a
great.