Using a parsec parser in the IO monadWhat is a monad?Monad in plain English? (For the OOP programmer with no FP background)Large-scale design in Haskell?A monad is just a monoid in the category of endofunctors, what's the problem?Using Parsec with Data.TextFull parser examples with parsec?What is the best way to use WriterT with Parsec?How to write a parsec parser for a list of interspersed elements?Why do we need monads?How to generalize repetitive parsing with Parsec

A ​Note ​on ​N!

Why is it that the natural deduction method can't test for invalidity?

With a Canadian student visa, can I spend a night at Vancouver before continuing to Toronto?

How to reduce LED flash rate (frequency)

Is it possible to determine the symmetric encryption method used by output size?

How much cash can I safely carry into the USA and avoid civil forfeiture?

US visa is under administrative processing, I need the passport back ASAP

How to verbalise code in Mathematica?

How to creep the reader out with what seems like a normal person?

Contradiction proof for inequality of P and NP?

Reducing vertical space in stackrel

Is there any limitation with Arduino Nano serial communication distance?

What makes accurate emulation of old systems a difficult task?

Is there really no use for MD5 anymore?

What happened to Captain America in Endgame?

Is the 5 MB static resource size limit 5,242,880 bytes or 5,000,000 bytes?

The Defining Moment

Repelling Blast: Must targets always be pushed back?

how to find the equation of a circle given points of the circle

What's the polite way to say "I need to urinate"?

Pass By Reference VS Pass by Value

What are the potential pitfalls when using metals as a currency?

What is the most expensive material in the world that could be used to create Pun-Pun's lute?

Examples of non trivial equivalence relations , I mean equivalence relations without the expression " same ... as" in their definition?



Using a parsec parser in the IO monad


What is a monad?Monad in plain English? (For the OOP programmer with no FP background)Large-scale design in Haskell?A monad is just a monoid in the category of endofunctors, what's the problem?Using Parsec with Data.TextFull parser examples with parsec?What is the best way to use WriterT with Parsec?How to write a parsec parser for a list of interspersed elements?Why do we need monads?How to generalize repetitive parsing with Parsec






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








1















I've defined a parser using Parsec, which has type Parsec Text () a for some a. I've also got a "deal with this chunk" function, which writes the thing I've parsed to a file and has type a -> IO (). The file format that it's parsing means that we get back to "top level" reasonably frequently.



Is there a way to take my original parser and "lift it" into the IO monad? I'm imagining something with the following type signature:



liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()


where the first argument is the pure parser and the second is the "do something with the thing I parsed" function.



Obviously, I can bodge together what I need by redefining my original parser in IO too, but that means my unit tests look horrible, and it just feels like the wrong approach.



Also, I can't do something crazy like calling runParserT because that would drop the source position information - if there's an error on line 1000 of the input, I'd like the error message to say so.



So is there a way to do this and, if so, how? Also, is this a sensible thing to do? I imagine that I'm at least managing to avoid accumulating the output data. And, assuming that I manage something like this, should I expect Parsec to manage to discard the input data that it's already dealt with?










share|improve this question

















  • 9





    Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

    – luqui
    Mar 22 at 18:29






  • 2





    I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

    – that other guy
    Mar 22 at 23:51











  • luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

    – Rupert Swarbrick
    Mar 23 at 12:17











  • @thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

    – Rupert Swarbrick
    Mar 25 at 9:54

















1















I've defined a parser using Parsec, which has type Parsec Text () a for some a. I've also got a "deal with this chunk" function, which writes the thing I've parsed to a file and has type a -> IO (). The file format that it's parsing means that we get back to "top level" reasonably frequently.



Is there a way to take my original parser and "lift it" into the IO monad? I'm imagining something with the following type signature:



liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()


where the first argument is the pure parser and the second is the "do something with the thing I parsed" function.



Obviously, I can bodge together what I need by redefining my original parser in IO too, but that means my unit tests look horrible, and it just feels like the wrong approach.



Also, I can't do something crazy like calling runParserT because that would drop the source position information - if there's an error on line 1000 of the input, I'd like the error message to say so.



So is there a way to do this and, if so, how? Also, is this a sensible thing to do? I imagine that I'm at least managing to avoid accumulating the output data. And, assuming that I manage something like this, should I expect Parsec to manage to discard the input data that it's already dealt with?










share|improve this question

















  • 9





    Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

    – luqui
    Mar 22 at 18:29






  • 2





    I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

    – that other guy
    Mar 22 at 23:51











  • luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

    – Rupert Swarbrick
    Mar 23 at 12:17











  • @thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

    – Rupert Swarbrick
    Mar 25 at 9:54













1












1








1








I've defined a parser using Parsec, which has type Parsec Text () a for some a. I've also got a "deal with this chunk" function, which writes the thing I've parsed to a file and has type a -> IO (). The file format that it's parsing means that we get back to "top level" reasonably frequently.



Is there a way to take my original parser and "lift it" into the IO monad? I'm imagining something with the following type signature:



liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()


where the first argument is the pure parser and the second is the "do something with the thing I parsed" function.



Obviously, I can bodge together what I need by redefining my original parser in IO too, but that means my unit tests look horrible, and it just feels like the wrong approach.



Also, I can't do something crazy like calling runParserT because that would drop the source position information - if there's an error on line 1000 of the input, I'd like the error message to say so.



So is there a way to do this and, if so, how? Also, is this a sensible thing to do? I imagine that I'm at least managing to avoid accumulating the output data. And, assuming that I manage something like this, should I expect Parsec to manage to discard the input data that it's already dealt with?










share|improve this question














I've defined a parser using Parsec, which has type Parsec Text () a for some a. I've also got a "deal with this chunk" function, which writes the thing I've parsed to a file and has type a -> IO (). The file format that it's parsing means that we get back to "top level" reasonably frequently.



Is there a way to take my original parser and "lift it" into the IO monad? I'm imagining something with the following type signature:



liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()


where the first argument is the pure parser and the second is the "do something with the thing I parsed" function.



Obviously, I can bodge together what I need by redefining my original parser in IO too, but that means my unit tests look horrible, and it just feels like the wrong approach.



Also, I can't do something crazy like calling runParserT because that would drop the source position information - if there's an error on line 1000 of the input, I'd like the error message to say so.



So is there a way to do this and, if so, how? Also, is this a sensible thing to do? I imagine that I'm at least managing to avoid accumulating the output data. And, assuming that I manage something like this, should I expect Parsec to manage to discard the input data that it's already dealt with?







haskell monads parsec io-monad






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 22 at 18:19









Rupert SwarbrickRupert Swarbrick

2,2921124




2,2921124







  • 9





    Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

    – luqui
    Mar 22 at 18:29






  • 2





    I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

    – that other guy
    Mar 22 at 23:51











  • luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

    – Rupert Swarbrick
    Mar 23 at 12:17











  • @thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

    – Rupert Swarbrick
    Mar 25 at 9:54












  • 9





    Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

    – luqui
    Mar 22 at 18:29






  • 2





    I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

    – that other guy
    Mar 22 at 23:51











  • luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

    – Rupert Swarbrick
    Mar 23 at 12:17











  • @thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

    – Rupert Swarbrick
    Mar 25 at 9:54







9




9





Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

– luqui
Mar 22 at 18:29





Why not define your original parser polymorphically. ParsecT Text () m, leaving m undecided. Then your pure tests can test it on Identity, but you can instantiate at IO when you need to.

– luqui
Mar 22 at 18:29




2




2





I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

– that other guy
Mar 22 at 23:51





I've used luqui's approach with great results for unit testing before, and I'd definitely do it again. If you still find yourself wanting to call runParserT for whichever reason, you can simply use setPosition to set Parsec's idea of the current source location (without skipping in the stream).

– that other guy
Mar 22 at 23:51













luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

– Rupert Swarbrick
Mar 23 at 12:17





luqui: Good point, that's exactly what I should be doing! Could you reply with an answer? I'll happily accept it.

– Rupert Swarbrick
Mar 23 at 12:17













@thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

– Rupert Swarbrick
Mar 25 at 9:54





@thatotherguy: Ah! Maybe that's actually a better approach for me - it will guarantee that Parsec doesn't need to hold on to any other internal state between top-levels. Thank you both.

– Rupert Swarbrick
Mar 25 at 9:54












1 Answer
1






active

oldest

votes


















0














Just so this question can be marked as answered: luqui's comment above explains how to do it.



The trick is to define all your parsers polymorphically, with type ParsecT Text () m (the definitions all end up looking like thing :: Monad m => Parsec Text () m MyType). Then you can instantiate with m the identity monad in the test-bench and equal to IO where they are used.






share|improve this answer























    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%2f55305679%2fusing-a-parsec-parser-in-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









    0














    Just so this question can be marked as answered: luqui's comment above explains how to do it.



    The trick is to define all your parsers polymorphically, with type ParsecT Text () m (the definitions all end up looking like thing :: Monad m => Parsec Text () m MyType). Then you can instantiate with m the identity monad in the test-bench and equal to IO where they are used.






    share|improve this answer



























      0














      Just so this question can be marked as answered: luqui's comment above explains how to do it.



      The trick is to define all your parsers polymorphically, with type ParsecT Text () m (the definitions all end up looking like thing :: Monad m => Parsec Text () m MyType). Then you can instantiate with m the identity monad in the test-bench and equal to IO where they are used.






      share|improve this answer

























        0












        0








        0







        Just so this question can be marked as answered: luqui's comment above explains how to do it.



        The trick is to define all your parsers polymorphically, with type ParsecT Text () m (the definitions all end up looking like thing :: Monad m => Parsec Text () m MyType). Then you can instantiate with m the identity monad in the test-bench and equal to IO where they are used.






        share|improve this answer













        Just so this question can be marked as answered: luqui's comment above explains how to do it.



        The trick is to define all your parsers polymorphically, with type ParsecT Text () m (the definitions all end up looking like thing :: Monad m => Parsec Text () m MyType). Then you can instantiate with m the identity monad in the test-bench and equal to IO where they are used.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 28 at 8:01









        Rupert SwarbrickRupert Swarbrick

        2,2921124




        2,2921124





























            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%2f55305679%2fusing-a-parsec-parser-in-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

            Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

            Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

            Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript