How to bring a monadic interpreter to the IO monad?
My question relates to the simple interpreter written in in this answer. I already asked a similar question before, which relates to the first non monadic interpreter in the answer behind the link. But there is a second monadic one, to which this question relates.
How could one add IO capabilities to the monadic interpreter (You need to scroll down because the answer contains two variants, the first being non-monadic and the second monadic.)? By this I simply mean adding a statement that uses putStrLn. I'm not that well versed in Haskell yet, but I'm guessing you can just combine the IO monad with the interpreter monad somehow. Can somebody point me in the right direction?
data Stmt
= Var := Exp
| While Exp Stmt
| Seq [Stmt]
| Print Exp -- a print statement
haskell interpreter
|
show 2 more comments
My question relates to the simple interpreter written in in this answer. I already asked a similar question before, which relates to the first non monadic interpreter in the answer behind the link. But there is a second monadic one, to which this question relates.
How could one add IO capabilities to the monadic interpreter (You need to scroll down because the answer contains two variants, the first being non-monadic and the second monadic.)? By this I simply mean adding a statement that uses putStrLn. I'm not that well versed in Haskell yet, but I'm guessing you can just combine the IO monad with the interpreter monad somehow. Can somebody point me in the right direction?
data Stmt
= Var := Exp
| While Exp Stmt
| Seq [Stmt]
| Print Exp -- a print statement
haskell interpreter
1
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
1
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19
|
show 2 more comments
My question relates to the simple interpreter written in in this answer. I already asked a similar question before, which relates to the first non monadic interpreter in the answer behind the link. But there is a second monadic one, to which this question relates.
How could one add IO capabilities to the monadic interpreter (You need to scroll down because the answer contains two variants, the first being non-monadic and the second monadic.)? By this I simply mean adding a statement that uses putStrLn. I'm not that well versed in Haskell yet, but I'm guessing you can just combine the IO monad with the interpreter monad somehow. Can somebody point me in the right direction?
data Stmt
= Var := Exp
| While Exp Stmt
| Seq [Stmt]
| Print Exp -- a print statement
haskell interpreter
My question relates to the simple interpreter written in in this answer. I already asked a similar question before, which relates to the first non monadic interpreter in the answer behind the link. But there is a second monadic one, to which this question relates.
How could one add IO capabilities to the monadic interpreter (You need to scroll down because the answer contains two variants, the first being non-monadic and the second monadic.)? By this I simply mean adding a statement that uses putStrLn. I'm not that well versed in Haskell yet, but I'm guessing you can just combine the IO monad with the interpreter monad somehow. Can somebody point me in the right direction?
data Stmt
= Var := Exp
| While Exp Stmt
| Seq [Stmt]
| Print Exp -- a print statement
haskell interpreter
haskell interpreter
edited Jan 1 at 11:25
John Smith
asked Jan 1 at 10:52
John SmithJohn Smith
1,6441816
1,6441816
1
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
1
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19
|
show 2 more comments
1
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
1
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19
1
1
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
1
1
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19
|
show 2 more comments
1 Answer
1
active
oldest
votes
A straightforward approach is to change Interp
to incorporate IO
.
newtype Interp a = Interp { runInterp :: Store -> IO (Either String (a, Store)) }
Then we just need to update the Monad
instance, rd
, wr
, and run
for the new internals of Interp
by sprinkling in some return
s and binds. For example, here’s the new Monad
instance:
instance Monad Interp where
return x = Interp $ r -> return (Right (x, r))
i >>= k =
Interp $ r -> do
res <- runInterp i r
case res of
Left msg -> return (Left msg)
Right (x, r') -> runInterp (k x) r'
fail msg = Interp $ _ -> return (Left msg)
One of the advantages of having abstracted out Interp
in the first place was so that we can make these kinds of changes without modifying the main part of the interpreter (eval
and exec
) at all.
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
Sure, you can use monad transformers here. For example,newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(withm
instead ofIO
) is a monad transformer. You factor theEither String
part out asEitherT
, and the(, Store)
part asWriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…
– Anders Kaseorg
Jan 3 at 11:16
Why would you useWriterT
as a replacement for(, Store)
? Isn'tStore
somewhat more like aStateT
?
– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
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%2f53994854%2fhow-to-bring-a-monadic-interpreter-to-the-io-monad%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 straightforward approach is to change Interp
to incorporate IO
.
newtype Interp a = Interp { runInterp :: Store -> IO (Either String (a, Store)) }
Then we just need to update the Monad
instance, rd
, wr
, and run
for the new internals of Interp
by sprinkling in some return
s and binds. For example, here’s the new Monad
instance:
instance Monad Interp where
return x = Interp $ r -> return (Right (x, r))
i >>= k =
Interp $ r -> do
res <- runInterp i r
case res of
Left msg -> return (Left msg)
Right (x, r') -> runInterp (k x) r'
fail msg = Interp $ _ -> return (Left msg)
One of the advantages of having abstracted out Interp
in the first place was so that we can make these kinds of changes without modifying the main part of the interpreter (eval
and exec
) at all.
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
Sure, you can use monad transformers here. For example,newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(withm
instead ofIO
) is a monad transformer. You factor theEither String
part out asEitherT
, and the(, Store)
part asWriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…
– Anders Kaseorg
Jan 3 at 11:16
Why would you useWriterT
as a replacement for(, Store)
? Isn'tStore
somewhat more like aStateT
?
– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
add a comment |
A straightforward approach is to change Interp
to incorporate IO
.
newtype Interp a = Interp { runInterp :: Store -> IO (Either String (a, Store)) }
Then we just need to update the Monad
instance, rd
, wr
, and run
for the new internals of Interp
by sprinkling in some return
s and binds. For example, here’s the new Monad
instance:
instance Monad Interp where
return x = Interp $ r -> return (Right (x, r))
i >>= k =
Interp $ r -> do
res <- runInterp i r
case res of
Left msg -> return (Left msg)
Right (x, r') -> runInterp (k x) r'
fail msg = Interp $ _ -> return (Left msg)
One of the advantages of having abstracted out Interp
in the first place was so that we can make these kinds of changes without modifying the main part of the interpreter (eval
and exec
) at all.
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
Sure, you can use monad transformers here. For example,newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(withm
instead ofIO
) is a monad transformer. You factor theEither String
part out asEitherT
, and the(, Store)
part asWriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…
– Anders Kaseorg
Jan 3 at 11:16
Why would you useWriterT
as a replacement for(, Store)
? Isn'tStore
somewhat more like aStateT
?
– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
add a comment |
A straightforward approach is to change Interp
to incorporate IO
.
newtype Interp a = Interp { runInterp :: Store -> IO (Either String (a, Store)) }
Then we just need to update the Monad
instance, rd
, wr
, and run
for the new internals of Interp
by sprinkling in some return
s and binds. For example, here’s the new Monad
instance:
instance Monad Interp where
return x = Interp $ r -> return (Right (x, r))
i >>= k =
Interp $ r -> do
res <- runInterp i r
case res of
Left msg -> return (Left msg)
Right (x, r') -> runInterp (k x) r'
fail msg = Interp $ _ -> return (Left msg)
One of the advantages of having abstracted out Interp
in the first place was so that we can make these kinds of changes without modifying the main part of the interpreter (eval
and exec
) at all.
A straightforward approach is to change Interp
to incorporate IO
.
newtype Interp a = Interp { runInterp :: Store -> IO (Either String (a, Store)) }
Then we just need to update the Monad
instance, rd
, wr
, and run
for the new internals of Interp
by sprinkling in some return
s and binds. For example, here’s the new Monad
instance:
instance Monad Interp where
return x = Interp $ r -> return (Right (x, r))
i >>= k =
Interp $ r -> do
res <- runInterp i r
case res of
Left msg -> return (Left msg)
Right (x, r') -> runInterp (k x) r'
fail msg = Interp $ _ -> return (Left msg)
One of the advantages of having abstracted out Interp
in the first place was so that we can make these kinds of changes without modifying the main part of the interpreter (eval
and exec
) at all.
answered Jan 3 at 5:12
Anders KaseorgAnders Kaseorg
1,790917
1,790917
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
Sure, you can use monad transformers here. For example,newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(withm
instead ofIO
) is a monad transformer. You factor theEither String
part out asEitherT
, and the(, Store)
part asWriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…
– Anders Kaseorg
Jan 3 at 11:16
Why would you useWriterT
as a replacement for(, Store)
? Isn'tStore
somewhat more like aStateT
?
– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
add a comment |
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
Sure, you can use monad transformers here. For example,newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(withm
instead ofIO
) is a monad transformer. You factor theEither String
part out asEitherT
, and the(, Store)
part asWriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…
– Anders Kaseorg
Jan 3 at 11:16
Why would you useWriterT
as a replacement for(, Store)
? Isn'tStore
somewhat more like aStateT
?
– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
I have been reading about monad transformers, while trying to figure this out. Do you think it might make sense to go that way? It seems (to me the unexperienced reader) that this could actually enable me to use different monads for different purposes (like Reader and Writer) with the same interpreter monad instead of just exposing the whole of IO.
– John Smith
Jan 3 at 11:10
1
1
Sure, you can use monad transformers here. For example,
newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(with m
instead of IO
) is a monad transformer. You factor the Either String
part out as EitherT
, and the (, Store)
part as WriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…– Anders Kaseorg
Jan 3 at 11:16
Sure, you can use monad transformers here. For example,
newtype Interp m a = Interp { runInterp :: Store -> m (Either String (a, Store)) }
(with m
instead of IO
) is a monad transformer. You factor the Either String
part out as EitherT
, and the (, Store)
part as WriterT
. It’s up to you how far you want to go down this path—the ability to keep generalizing your program with more and more complicated abstractions is simultaneously one of Haskell’s greatest strengths and one of Haskell’s greatest weaknesses…– Anders Kaseorg
Jan 3 at 11:16
Why would you use
WriterT
as a replacement for (, Store)
? Isn't Store
somewhat more like a StateT
?– John Smith
Jan 16 at 9:36
Why would you use
WriterT
as a replacement for (, Store)
? Isn't Store
somewhat more like a StateT
?– John Smith
Jan 16 at 9:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
@JohnSmith You're right, that's what I should have written.
– Anders Kaseorg
Jan 16 at 17:36
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%2f53994854%2fhow-to-bring-a-monadic-interpreter-to-the-io-monad%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
1
why have you asked this twice? stackoverflow.com/questions/53994496/… (You appear to have even accepted an answer to the last one.)
– Robin Zigmond
Jan 1 at 11:06
Possible duplicate of How to bring an interpreter to the IO monad?
– AJFarmar
Jan 1 at 11:12
didn't I write that? the first question and it's accepted answer relate to the non-monadic parser while this one relates to the monadic parser
– John Smith
Jan 1 at 11:19
1
Rather than the IO monad, you may want to use the Writer monad. Then you can do whatever you want with the result afterwards, like printing.
– 4castle
Jan 1 at 14:38
@Robin Zigmond: It would be nice if somebody would provide constructive critique. I hope my edits made it clear, that this is not the same question and that I am also looking for an answer to this question not just to the other one. Should I create a new question copying the monadic parser into it and asking how I can add a print statement?
– John Smith
Jan 2 at 10:19