How can I get GHC to emit a warning for a given function?












3















Suppose I've decided that everywhere in a given code base (package) I want to use a custom getCurrentTimeMicroseconds rather than getCurrentTime. Is there a way for me to get GHC to emit warnings me about uses of getCurrentTime, only in that code base? (Not for anything upstream or downstream.)



Bonus question, suppose I want to selectively allow usages with an explicit annotation at the use site (preferably not module-wide). Is this also possible?










share|improve this question























  • Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

    – Robert Harvey
    Jan 18 at 16:25











  • @RobertHarvey it does not, at present.

    – Dan Burton
    Jan 18 at 16:37
















3















Suppose I've decided that everywhere in a given code base (package) I want to use a custom getCurrentTimeMicroseconds rather than getCurrentTime. Is there a way for me to get GHC to emit warnings me about uses of getCurrentTime, only in that code base? (Not for anything upstream or downstream.)



Bonus question, suppose I want to selectively allow usages with an explicit annotation at the use site (preferably not module-wide). Is this also possible?










share|improve this question























  • Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

    – Robert Harvey
    Jan 18 at 16:25











  • @RobertHarvey it does not, at present.

    – Dan Burton
    Jan 18 at 16:37














3












3








3








Suppose I've decided that everywhere in a given code base (package) I want to use a custom getCurrentTimeMicroseconds rather than getCurrentTime. Is there a way for me to get GHC to emit warnings me about uses of getCurrentTime, only in that code base? (Not for anything upstream or downstream.)



Bonus question, suppose I want to selectively allow usages with an explicit annotation at the use site (preferably not module-wide). Is this also possible?










share|improve this question














Suppose I've decided that everywhere in a given code base (package) I want to use a custom getCurrentTimeMicroseconds rather than getCurrentTime. Is there a way for me to get GHC to emit warnings me about uses of getCurrentTime, only in that code base? (Not for anything upstream or downstream.)



Bonus question, suppose I want to selectively allow usages with an explicit annotation at the use site (preferably not module-wide). Is this also possible?







haskell ghc






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 18 at 16:22









Dan BurtonDan Burton

37.4k2097179




37.4k2097179













  • Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

    – Robert Harvey
    Jan 18 at 16:25











  • @RobertHarvey it does not, at present.

    – Dan Burton
    Jan 18 at 16:37



















  • Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

    – Robert Harvey
    Jan 18 at 16:25











  • @RobertHarvey it does not, at present.

    – Dan Burton
    Jan 18 at 16:37

















Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

– Robert Harvey
Jan 18 at 16:25





Does getCurrentTimeMicroseconds emit a different type than getCurrentTime?

– Robert Harvey
Jan 18 at 16:25













@RobertHarvey it does not, at present.

– Dan Burton
Jan 18 at 16:37





@RobertHarvey it does not, at present.

– Dan Burton
Jan 18 at 16:37












2 Answers
2






active

oldest

votes


















3














This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.



For example, you could wrap UTCTime like so:



newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }

microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
microsecondsFromPicos = ...

getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime


And use the new type everywhere in your package that you need times to have this property.



If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.



That makes any misuse an error, not a warning, but in most cases that's what you want anyway.



When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.






share|improve this answer































    1














    I can't think of a way to do this right now, but I think the closest you can get is something like:




    • create a new package my-time that depends on time


    • re-export your shim functions annotated with warnings, like



      import qualified Data.Time as Time
      {-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
      getCurrentTime = Time.getCurrentTime


    • depend on my-time in your packages



    obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.






    share|improve this answer
























    • It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

      – jberryman
      Jan 18 at 16:48











    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%2f54257838%2fhow-can-i-get-ghc-to-emit-a-warning-for-a-given-function%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.



    For example, you could wrap UTCTime like so:



    newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }

    microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
    microsecondsFromPicos = ...

    getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
    getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime


    And use the new type everywhere in your package that you need times to have this property.



    If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.



    That makes any misuse an error, not a warning, but in most cases that's what you want anyway.



    When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.






    share|improve this answer




























      3














      This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.



      For example, you could wrap UTCTime like so:



      newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }

      microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
      microsecondsFromPicos = ...

      getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
      getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime


      And use the new type everywhere in your package that you need times to have this property.



      If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.



      That makes any misuse an error, not a warning, but in most cases that's what you want anyway.



      When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.






      share|improve this answer


























        3












        3








        3







        This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.



        For example, you could wrap UTCTime like so:



        newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }

        microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
        microsecondsFromPicos = ...

        getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
        getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime


        And use the new type everywhere in your package that you need times to have this property.



        If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.



        That makes any misuse an error, not a warning, but in most cases that's what you want anyway.



        When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.






        share|improve this answer













        This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.



        For example, you could wrap UTCTime like so:



        newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }

        microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
        microsecondsFromPicos = ...

        getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
        getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime


        And use the new type everywhere in your package that you need times to have this property.



        If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.



        That makes any misuse an error, not a warning, but in most cases that's what you want anyway.



        When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 18 at 16:52









        Moss PrescottMoss Prescott

        1043




        1043

























            1














            I can't think of a way to do this right now, but I think the closest you can get is something like:




            • create a new package my-time that depends on time


            • re-export your shim functions annotated with warnings, like



              import qualified Data.Time as Time
              {-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
              getCurrentTime = Time.getCurrentTime


            • depend on my-time in your packages



            obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.






            share|improve this answer
























            • It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

              – jberryman
              Jan 18 at 16:48
















            1














            I can't think of a way to do this right now, but I think the closest you can get is something like:




            • create a new package my-time that depends on time


            • re-export your shim functions annotated with warnings, like



              import qualified Data.Time as Time
              {-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
              getCurrentTime = Time.getCurrentTime


            • depend on my-time in your packages



            obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.






            share|improve this answer
























            • It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

              – jberryman
              Jan 18 at 16:48














            1












            1








            1







            I can't think of a way to do this right now, but I think the closest you can get is something like:




            • create a new package my-time that depends on time


            • re-export your shim functions annotated with warnings, like



              import qualified Data.Time as Time
              {-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
              getCurrentTime = Time.getCurrentTime


            • depend on my-time in your packages



            obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.






            share|improve this answer













            I can't think of a way to do this right now, but I think the closest you can get is something like:




            • create a new package my-time that depends on time


            • re-export your shim functions annotated with warnings, like



              import qualified Data.Time as Time
              {-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
              getCurrentTime = Time.getCurrentTime


            • depend on my-time in your packages



            obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 18 at 16:43









            jberrymanjberryman

            11.7k33471




            11.7k33471













            • It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

              – jberryman
              Jan 18 at 16:48



















            • It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

              – jberryman
              Jan 18 at 16:48

















            It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

            – jberryman
            Jan 18 at 16:48





            It might be nice if e.g. stack could allow local packages with conflicting names to shadow the published hackage version for multi-package projects

            – jberryman
            Jan 18 at 16:48


















            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%2f54257838%2fhow-can-i-get-ghc-to-emit-a-warning-for-a-given-function%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

            Liquibase includeAll doesn't find base path

            How to use setInterval in EJS file?

            Petrus Granier-Deferre