How to bring a monadic interpreter to the IO monad?












-1















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









share|improve this question




















  • 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















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









share|improve this question




















  • 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








-1








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









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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














  • 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












1 Answer
1






active

oldest

votes


















3
















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 returns 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.






share|improve this answer
























  • 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)) } (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











  • @JohnSmith You're right, that's what I should have written.

    – Anders Kaseorg
    Jan 16 at 17:36











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
});


}
});














draft saved

draft discarded


















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









3
















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 returns 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.






share|improve this answer
























  • 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)) } (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











  • @JohnSmith You're right, that's what I should have written.

    – Anders Kaseorg
    Jan 16 at 17:36
















3
















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 returns 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.






share|improve this answer
























  • 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)) } (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











  • @JohnSmith You're right, that's what I should have written.

    – Anders Kaseorg
    Jan 16 at 17:36














3












3








3









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 returns 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.






share|improve this answer















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 returns 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.







share|improve this answer












share|improve this answer



share|improve this answer










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)) } (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











  • @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






  • 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













  • 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

















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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

Npm cannot find a required file even through it is in the searched directory