Curious about why get in StateT monad transformer returns a instead of (a, s)How does this State monad code works?Haskell Monad Transformer Stack and Type Signatureshow can I implement this monad transformer with a continuation?How do I actually execute a StateT monad along with IO?Wadler's paper: How is a tuple a function?StateT and non-determinism monad: a simple exampleWhy do we need monads?Using liftIO and monad transformers, why is the type of a bound variable IO List instead of List?Is it possible to use IO inside State monad, without using StateT and STHaskell - no output from within StateT monadBacktrack over underlying monad in Monad Transformer
What can I do with a research project that is my university’s intellectual property?
When to remove insignificant variables?
Has there been any indication at all that further negotiation between the UK and EU is possible?
JSON selector class in Python
What reason would an alien civilization have for building a Dyson Sphere (or Swarm) if cheap Nuclear fusion is available?
Why did pressing the joystick button spit out keypresses?
How is hair tissue mineral analysis performed?
What does the hyphen "-" mean in "tar xzf -"?
Do I have any obligations to my PhD supervisor's requests after I have graduated?
Should I prioritize my 401k over my student loans?
What is "industrial ethernet"?
How long would it take to cross the Channel in 1890's?
Explain why a line can never intersect a plane in exactly two points.
Did the CIA blow up a Siberian pipeline in 1982?
Output of "$OSTYPE:6" on old releases of Mac OS X
How would modern naval warfare have to have developed differently for battleships to still be relevant in the 21st century?
How does a blind passenger not die, if driver becomes unconscious
Can there be an UN resolution to remove a country from the UNSC?
Why does the Saturn V have standalone inter-stage rings?
How much will studying magic in an academy cost?
How do I set an alias to a terminal line?
Unusual mail headers, evidence of an attempted attack. Have I been pwned?
How to draw this center trajectory of rolling ball?
Are all instances of trolls turning to stone ultimately references back to Tolkien?
Curious about why get in StateT monad transformer returns a instead of (a, s)
How does this State monad code works?Haskell Monad Transformer Stack and Type Signatureshow can I implement this monad transformer with a continuation?How do I actually execute a StateT monad along with IO?Wadler's paper: How is a tuple a function?StateT and non-determinism monad: a simple exampleWhy do we need monads?Using liftIO and monad transformers, why is the type of a bound variable IO List instead of List?Is it possible to use IO inside State monad, without using StateT and STHaskell - no output from within StateT monadBacktrack over underlying monad in Monad Transformer
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I was reading the StateT monad transformer's source, as it reads like this:
get :: (Monad m) => StateT s m s
get = state $ s -> (s, s)
I expanded the above code by switching out state
and got this, but still fail to see why it's not returning a tuple.
a <- StateT (return . ( s -> (s, s)))
From the code above it seemed get
returns a tuple (s, s)
, which looked fine, but I'm wondering why when using it, get
returned an Int
, instead of (Int, Int)
?
I traced a lot of source code trying to find when or what changed it but to no avail.
w :: StateT Int IO String
w = do
a <- get
liftIO $ print a -- 2, but why? shouldn't this be (2, 2) instead?
return $ show a
result = runStateT w 2 -- ("2",2)
haskell
|
show 8 more comments
I was reading the StateT monad transformer's source, as it reads like this:
get :: (Monad m) => StateT s m s
get = state $ s -> (s, s)
I expanded the above code by switching out state
and got this, but still fail to see why it's not returning a tuple.
a <- StateT (return . ( s -> (s, s)))
From the code above it seemed get
returns a tuple (s, s)
, which looked fine, but I'm wondering why when using it, get
returned an Int
, instead of (Int, Int)
?
I traced a lot of source code trying to find when or what changed it but to no avail.
w :: StateT Int IO String
w = do
a <- get
liftIO $ print a -- 2, but why? shouldn't this be (2, 2) instead?
return $ show a
result = runStateT w 2 -- ("2",2)
haskell
get
returns a value of type(StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the<-
notation to "extract the underlying value",a
is simply aString
.
– Robin Zigmond
Mar 25 at 8:50
3
@DonKlein No,get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines>>=
to pass part of that return value, once it actually gets called viarunState(T)
, as the argument to the next function.
– chepner
Mar 25 at 12:09
1
see thek a
in the last line of>>=
implementation there,runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. itsfst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while thes'
in( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" thea
"value", ands
"state" is maintained on the side for us.
– Will Ness
Mar 25 at 12:37
1
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
1
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07
|
show 8 more comments
I was reading the StateT monad transformer's source, as it reads like this:
get :: (Monad m) => StateT s m s
get = state $ s -> (s, s)
I expanded the above code by switching out state
and got this, but still fail to see why it's not returning a tuple.
a <- StateT (return . ( s -> (s, s)))
From the code above it seemed get
returns a tuple (s, s)
, which looked fine, but I'm wondering why when using it, get
returned an Int
, instead of (Int, Int)
?
I traced a lot of source code trying to find when or what changed it but to no avail.
w :: StateT Int IO String
w = do
a <- get
liftIO $ print a -- 2, but why? shouldn't this be (2, 2) instead?
return $ show a
result = runStateT w 2 -- ("2",2)
haskell
I was reading the StateT monad transformer's source, as it reads like this:
get :: (Monad m) => StateT s m s
get = state $ s -> (s, s)
I expanded the above code by switching out state
and got this, but still fail to see why it's not returning a tuple.
a <- StateT (return . ( s -> (s, s)))
From the code above it seemed get
returns a tuple (s, s)
, which looked fine, but I'm wondering why when using it, get
returned an Int
, instead of (Int, Int)
?
I traced a lot of source code trying to find when or what changed it but to no avail.
w :: StateT Int IO String
w = do
a <- get
liftIO $ print a -- 2, but why? shouldn't this be (2, 2) instead?
return $ show a
result = runStateT w 2 -- ("2",2)
haskell
haskell
edited Mar 25 at 14:08
chepner
274k40266359
274k40266359
asked Mar 25 at 8:47
Don KleinDon Klein
715
715
get
returns a value of type(StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the<-
notation to "extract the underlying value",a
is simply aString
.
– Robin Zigmond
Mar 25 at 8:50
3
@DonKlein No,get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines>>=
to pass part of that return value, once it actually gets called viarunState(T)
, as the argument to the next function.
– chepner
Mar 25 at 12:09
1
see thek a
in the last line of>>=
implementation there,runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. itsfst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while thes'
in( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" thea
"value", ands
"state" is maintained on the side for us.
– Will Ness
Mar 25 at 12:37
1
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
1
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07
|
show 8 more comments
get
returns a value of type(StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the<-
notation to "extract the underlying value",a
is simply aString
.
– Robin Zigmond
Mar 25 at 8:50
3
@DonKlein No,get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines>>=
to pass part of that return value, once it actually gets called viarunState(T)
, as the argument to the next function.
– chepner
Mar 25 at 12:09
1
see thek a
in the last line of>>=
implementation there,runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. itsfst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while thes'
in( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" thea
"value", ands
"state" is maintained on the side for us.
– Will Ness
Mar 25 at 12:37
1
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
1
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07
get
returns a value of type (StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the <-
notation to "extract the underlying value", a
is simply a String
.– Robin Zigmond
Mar 25 at 8:50
get
returns a value of type (StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the <-
notation to "extract the underlying value", a
is simply a String
.– Robin Zigmond
Mar 25 at 8:50
3
3
@DonKlein No,
get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines >>=
to pass part of that return value, once it actually gets called via runState(T)
, as the argument to the next function.– chepner
Mar 25 at 12:09
@DonKlein No,
get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines >>=
to pass part of that return value, once it actually gets called via runState(T)
, as the argument to the next function.– chepner
Mar 25 at 12:09
1
1
see the
k a
in the last line of >>=
implementation there, runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. its fst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while the s'
in ( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" the a
"value", and s
"state" is maintained on the side for us.– Will Ness
Mar 25 at 12:37
see the
k a
in the last line of >>=
implementation there, runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. its fst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while the s'
in ( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" the a
"value", and s
"state" is maintained on the side for us.– Will Ness
Mar 25 at 12:37
1
1
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
1
1
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07
|
show 8 more comments
1 Answer
1
active
oldest
votes
A value of type StateT s m a
, modulo newtype
wrappers, is a function with type s -> m (a, s)
.
The function (return . ( s -> (s, s)))
has type s -> m (s, s)
, hence once it is wrapped by the StateT
constructor becomes a value of type StateT s m s
.
Note that a value of type StateT s m (s, s)
would instead involve a function of type s -> m (s, (s, s))
which is not what we are using here.
Your confusion seem to arise from the "other" s
in m (s, s)
, which does not contribute to x
when we run x <- get
. To understand why, it's useful to think to think to what a stateful computation performs:
- First, we read the old state of type
s
. This is thes -> ..
part in the types -> m (a, s)
. - Then, we run some action in the monad
m
. This is the.. -> m ..
part in the types -> m (a, s)
.- The monadic action returns a new state, to replace the old one. This is the
.. -> .. (.., s)
part in the types -> m (a, s)
. - Finally, monadic action also returns a value, of a possibly different type
a
. This the.. -> .. (a, ..)
part in the types -> m (a, s)
.
- The monadic action returns a new state, to replace the old one. This is the
Running x <- action
handles all these types automatically for us, and lets x
to have the result type a
, only.
Concretely, consider this imperative pseudo-code:
global n: int
def foo():
if n > 5:
print ">5"
n = 8
return "hello"
else:
print "not >5"
n = 10
return "greetings"
In an imperative language, we would type this as foo(): string
, since it returns a string, disregarding its side effects to the global n: int
and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
^-- the printed stuff
^-- the returned string
^-- the new n
Again, running x <- foo()
we want x: string
, not x: (string, int)
, following what would happen in an imperative language.
If instead we had a function
global n: int
def bar():
old_n = n
n = n + 5
return old_n
we would use the type
Int -> IO (Int, Int)
since the returned value is an Int
now. Similarly,
global n: int
def get():
return n
could use the same type
Int -> IO (Int, Int)
Now, one might argue that the second Int
is not strictly necessary here, since get()
is not really producing a new state -- it's not changing the value of n
. Still, it's convenient to use a type of the same form, s -> m (a, s)
, as any function which could change the state. This is so that it can be used together with any other function having a similar type.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55334033%2fcurious-about-why-get-in-statet-monad-transformer-returns-a-instead-of-a-s%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
A value of type StateT s m a
, modulo newtype
wrappers, is a function with type s -> m (a, s)
.
The function (return . ( s -> (s, s)))
has type s -> m (s, s)
, hence once it is wrapped by the StateT
constructor becomes a value of type StateT s m s
.
Note that a value of type StateT s m (s, s)
would instead involve a function of type s -> m (s, (s, s))
which is not what we are using here.
Your confusion seem to arise from the "other" s
in m (s, s)
, which does not contribute to x
when we run x <- get
. To understand why, it's useful to think to think to what a stateful computation performs:
- First, we read the old state of type
s
. This is thes -> ..
part in the types -> m (a, s)
. - Then, we run some action in the monad
m
. This is the.. -> m ..
part in the types -> m (a, s)
.- The monadic action returns a new state, to replace the old one. This is the
.. -> .. (.., s)
part in the types -> m (a, s)
. - Finally, monadic action also returns a value, of a possibly different type
a
. This the.. -> .. (a, ..)
part in the types -> m (a, s)
.
- The monadic action returns a new state, to replace the old one. This is the
Running x <- action
handles all these types automatically for us, and lets x
to have the result type a
, only.
Concretely, consider this imperative pseudo-code:
global n: int
def foo():
if n > 5:
print ">5"
n = 8
return "hello"
else:
print "not >5"
n = 10
return "greetings"
In an imperative language, we would type this as foo(): string
, since it returns a string, disregarding its side effects to the global n: int
and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
^-- the printed stuff
^-- the returned string
^-- the new n
Again, running x <- foo()
we want x: string
, not x: (string, int)
, following what would happen in an imperative language.
If instead we had a function
global n: int
def bar():
old_n = n
n = n + 5
return old_n
we would use the type
Int -> IO (Int, Int)
since the returned value is an Int
now. Similarly,
global n: int
def get():
return n
could use the same type
Int -> IO (Int, Int)
Now, one might argue that the second Int
is not strictly necessary here, since get()
is not really producing a new state -- it's not changing the value of n
. Still, it's convenient to use a type of the same form, s -> m (a, s)
, as any function which could change the state. This is so that it can be used together with any other function having a similar type.
add a comment |
A value of type StateT s m a
, modulo newtype
wrappers, is a function with type s -> m (a, s)
.
The function (return . ( s -> (s, s)))
has type s -> m (s, s)
, hence once it is wrapped by the StateT
constructor becomes a value of type StateT s m s
.
Note that a value of type StateT s m (s, s)
would instead involve a function of type s -> m (s, (s, s))
which is not what we are using here.
Your confusion seem to arise from the "other" s
in m (s, s)
, which does not contribute to x
when we run x <- get
. To understand why, it's useful to think to think to what a stateful computation performs:
- First, we read the old state of type
s
. This is thes -> ..
part in the types -> m (a, s)
. - Then, we run some action in the monad
m
. This is the.. -> m ..
part in the types -> m (a, s)
.- The monadic action returns a new state, to replace the old one. This is the
.. -> .. (.., s)
part in the types -> m (a, s)
. - Finally, monadic action also returns a value, of a possibly different type
a
. This the.. -> .. (a, ..)
part in the types -> m (a, s)
.
- The monadic action returns a new state, to replace the old one. This is the
Running x <- action
handles all these types automatically for us, and lets x
to have the result type a
, only.
Concretely, consider this imperative pseudo-code:
global n: int
def foo():
if n > 5:
print ">5"
n = 8
return "hello"
else:
print "not >5"
n = 10
return "greetings"
In an imperative language, we would type this as foo(): string
, since it returns a string, disregarding its side effects to the global n: int
and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
^-- the printed stuff
^-- the returned string
^-- the new n
Again, running x <- foo()
we want x: string
, not x: (string, int)
, following what would happen in an imperative language.
If instead we had a function
global n: int
def bar():
old_n = n
n = n + 5
return old_n
we would use the type
Int -> IO (Int, Int)
since the returned value is an Int
now. Similarly,
global n: int
def get():
return n
could use the same type
Int -> IO (Int, Int)
Now, one might argue that the second Int
is not strictly necessary here, since get()
is not really producing a new state -- it's not changing the value of n
. Still, it's convenient to use a type of the same form, s -> m (a, s)
, as any function which could change the state. This is so that it can be used together with any other function having a similar type.
add a comment |
A value of type StateT s m a
, modulo newtype
wrappers, is a function with type s -> m (a, s)
.
The function (return . ( s -> (s, s)))
has type s -> m (s, s)
, hence once it is wrapped by the StateT
constructor becomes a value of type StateT s m s
.
Note that a value of type StateT s m (s, s)
would instead involve a function of type s -> m (s, (s, s))
which is not what we are using here.
Your confusion seem to arise from the "other" s
in m (s, s)
, which does not contribute to x
when we run x <- get
. To understand why, it's useful to think to think to what a stateful computation performs:
- First, we read the old state of type
s
. This is thes -> ..
part in the types -> m (a, s)
. - Then, we run some action in the monad
m
. This is the.. -> m ..
part in the types -> m (a, s)
.- The monadic action returns a new state, to replace the old one. This is the
.. -> .. (.., s)
part in the types -> m (a, s)
. - Finally, monadic action also returns a value, of a possibly different type
a
. This the.. -> .. (a, ..)
part in the types -> m (a, s)
.
- The monadic action returns a new state, to replace the old one. This is the
Running x <- action
handles all these types automatically for us, and lets x
to have the result type a
, only.
Concretely, consider this imperative pseudo-code:
global n: int
def foo():
if n > 5:
print ">5"
n = 8
return "hello"
else:
print "not >5"
n = 10
return "greetings"
In an imperative language, we would type this as foo(): string
, since it returns a string, disregarding its side effects to the global n: int
and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
^-- the printed stuff
^-- the returned string
^-- the new n
Again, running x <- foo()
we want x: string
, not x: (string, int)
, following what would happen in an imperative language.
If instead we had a function
global n: int
def bar():
old_n = n
n = n + 5
return old_n
we would use the type
Int -> IO (Int, Int)
since the returned value is an Int
now. Similarly,
global n: int
def get():
return n
could use the same type
Int -> IO (Int, Int)
Now, one might argue that the second Int
is not strictly necessary here, since get()
is not really producing a new state -- it's not changing the value of n
. Still, it's convenient to use a type of the same form, s -> m (a, s)
, as any function which could change the state. This is so that it can be used together with any other function having a similar type.
A value of type StateT s m a
, modulo newtype
wrappers, is a function with type s -> m (a, s)
.
The function (return . ( s -> (s, s)))
has type s -> m (s, s)
, hence once it is wrapped by the StateT
constructor becomes a value of type StateT s m s
.
Note that a value of type StateT s m (s, s)
would instead involve a function of type s -> m (s, (s, s))
which is not what we are using here.
Your confusion seem to arise from the "other" s
in m (s, s)
, which does not contribute to x
when we run x <- get
. To understand why, it's useful to think to think to what a stateful computation performs:
- First, we read the old state of type
s
. This is thes -> ..
part in the types -> m (a, s)
. - Then, we run some action in the monad
m
. This is the.. -> m ..
part in the types -> m (a, s)
.- The monadic action returns a new state, to replace the old one. This is the
.. -> .. (.., s)
part in the types -> m (a, s)
. - Finally, monadic action also returns a value, of a possibly different type
a
. This the.. -> .. (a, ..)
part in the types -> m (a, s)
.
- The monadic action returns a new state, to replace the old one. This is the
Running x <- action
handles all these types automatically for us, and lets x
to have the result type a
, only.
Concretely, consider this imperative pseudo-code:
global n: int
def foo():
if n > 5:
print ">5"
n = 8
return "hello"
else:
print "not >5"
n = 10
return "greetings"
In an imperative language, we would type this as foo(): string
, since it returns a string, disregarding its side effects to the global n: int
and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
^-- the printed stuff
^-- the returned string
^-- the new n
Again, running x <- foo()
we want x: string
, not x: (string, int)
, following what would happen in an imperative language.
If instead we had a function
global n: int
def bar():
old_n = n
n = n + 5
return old_n
we would use the type
Int -> IO (Int, Int)
since the returned value is an Int
now. Similarly,
global n: int
def get():
return n
could use the same type
Int -> IO (Int, Int)
Now, one might argue that the second Int
is not strictly necessary here, since get()
is not really producing a new state -- it's not changing the value of n
. Still, it's convenient to use a type of the same form, s -> m (a, s)
, as any function which could change the state. This is so that it can be used together with any other function having a similar type.
edited Mar 25 at 13:12
Will Ness
48.3k471131
48.3k471131
answered Mar 25 at 12:36
chichi
79.6k288151
79.6k288151
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55334033%2fcurious-about-why-get-in-statet-monad-transformer-returns-a-instead-of-a-s%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
get
returns a value of type(StateT Int IO) String
(I've put the parentheses in to be more explicit, they are implied anyway), so using the<-
notation to "extract the underlying value",a
is simply aString
.– Robin Zigmond
Mar 25 at 8:50
3
@DonKlein No,
get
doesn't return anything. It is a value that wraps a function that returns a tuple. Its monad instance defines>>=
to pass part of that return value, once it actually gets called viarunState(T)
, as the argument to the next function.– chepner
Mar 25 at 12:09
1
see the
k a
in the last line of>>=
implementation there,runStateT (k a) s'
? that's what it means that only the part of the tuple - i.e. itsfst
field - is passed along as the "returned value" from a previous computation step into the next computation step, while thes'
in( a , s')
is tagging along as part of the stateful computation "pipeline". So we "compute" thea
"value", ands
"state" is maintained on the side for us.– Will Ness
Mar 25 at 12:37
1
see e.g. this for some illuminating (hopefully) re-writes in the answers. (disclaimer: one of them is by me). it's for simple State (no transformers) so should be simpler to follow. transformers just juggle the additional monads around, but the essence of state passing is the same.
– Will Ness
Mar 25 at 13:18
1
Don't put an answer in the question itself. You can post an answer to your own question if you fee the need.
– chepner
Mar 25 at 14:07