Constructing a Nat type












0















I'm currently learning about using Nat from GHC.TypeLits



I am trying to lift an integer to the type level for testing via these definitions:



type IntNat (t::Nat) = Int

incNat :: IntNat t -> IntNat (t + 1)
incNat n = n + 1

fromInt :: Int -> IntNat t
fromInt(0) = (0 :: IntNat 0)
fromInt(n) = incNat (fromInt(n-1))

four = fromInt 4


From my understanding this should result in:



four = 4 :: IntNat (Nat 4)


However I am getting:



four = 4 :: IntNat t


Where am I going wrong, is it just that fromInt is erasing the type information?










share|improve this question


















  • 1





    I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

    – AJFarmar
    Jan 3 at 18:27








  • 1





    According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

    – chi
    Jan 3 at 18:35






  • 1





    It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

    – Thomas M. DuBuisson
    Jan 3 at 18:52
















0















I'm currently learning about using Nat from GHC.TypeLits



I am trying to lift an integer to the type level for testing via these definitions:



type IntNat (t::Nat) = Int

incNat :: IntNat t -> IntNat (t + 1)
incNat n = n + 1

fromInt :: Int -> IntNat t
fromInt(0) = (0 :: IntNat 0)
fromInt(n) = incNat (fromInt(n-1))

four = fromInt 4


From my understanding this should result in:



four = 4 :: IntNat (Nat 4)


However I am getting:



four = 4 :: IntNat t


Where am I going wrong, is it just that fromInt is erasing the type information?










share|improve this question


















  • 1





    I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

    – AJFarmar
    Jan 3 at 18:27








  • 1





    According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

    – chi
    Jan 3 at 18:35






  • 1





    It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

    – Thomas M. DuBuisson
    Jan 3 at 18:52














0












0








0








I'm currently learning about using Nat from GHC.TypeLits



I am trying to lift an integer to the type level for testing via these definitions:



type IntNat (t::Nat) = Int

incNat :: IntNat t -> IntNat (t + 1)
incNat n = n + 1

fromInt :: Int -> IntNat t
fromInt(0) = (0 :: IntNat 0)
fromInt(n) = incNat (fromInt(n-1))

four = fromInt 4


From my understanding this should result in:



four = 4 :: IntNat (Nat 4)


However I am getting:



four = 4 :: IntNat t


Where am I going wrong, is it just that fromInt is erasing the type information?










share|improve this question














I'm currently learning about using Nat from GHC.TypeLits



I am trying to lift an integer to the type level for testing via these definitions:



type IntNat (t::Nat) = Int

incNat :: IntNat t -> IntNat (t + 1)
incNat n = n + 1

fromInt :: Int -> IntNat t
fromInt(0) = (0 :: IntNat 0)
fromInt(n) = incNat (fromInt(n-1))

four = fromInt 4


From my understanding this should result in:



four = 4 :: IntNat (Nat 4)


However I am getting:



four = 4 :: IntNat t


Where am I going wrong, is it just that fromInt is erasing the type information?







haskell types






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 3 at 18:15









Cjen1Cjen1

9351733




9351733








  • 1





    I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

    – AJFarmar
    Jan 3 at 18:27








  • 1





    According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

    – chi
    Jan 3 at 18:35






  • 1





    It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

    – Thomas M. DuBuisson
    Jan 3 at 18:52














  • 1





    I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

    – AJFarmar
    Jan 3 at 18:27








  • 1





    According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

    – chi
    Jan 3 at 18:35






  • 1





    It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

    – Thomas M. DuBuisson
    Jan 3 at 18:52








1




1





I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

– AJFarmar
Jan 3 at 18:27







I doubt that fromInt compiles. Could you produce an MCVE to show your problem?

– AJFarmar
Jan 3 at 18:27






1




1





According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

– chi
Jan 3 at 18:35





According to your definition IntNat t = Int for all t. Your signatures are exactly equivalent to incNat :: Int->Int and fromInt :: Int->Int. four has types IntNat (Nat 0), IntNat (Nat 1), ..., all of them actually being Int. For some reason, the type inference engine prefer the form IntNat t, as if it were the most general type (it is, but so are all the others). Note that, crucially, you are using a type synonym and not a newtype.

– chi
Jan 3 at 18:35




1




1





It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

– Thomas M. DuBuisson
Jan 3 at 18:52





It is quite clear that fromInt :: Int -> IntNat t so any time you apply it to a value of type Int you will get a value of type IntNat t. You seem to be wanting dependent types.

– Thomas M. DuBuisson
Jan 3 at 18:52












1 Answer
1






active

oldest

votes


















2














Because you defined a type synonym, and not a newtype, the meaning is quite different than what you seem to think. Roughly, IntNat _ will unify with Int and thus any other IntNat _.



You can try this out by defining other intnats and see them unify in, say, a list:



*Main> let five = 5 :: IntNat 99
*Main> let xs = [four, five] :: [IntNat 42]
*Main> :t xs
xs :: [IntNat 42]


or using a single intnat:



*Main> let four' = four :: IntNat 1000
*Main> :t four'
four' :: IntNat 1000


Instead consider using a newtype, such as newtype IntNat (n :: Nat) = IN Int. You'd get an error like:



• Couldn't match type ‘t’ with ‘0’
‘t’ is a rigid type variable bound by
the type signature for:
fromInt :: forall (t :: Nat). Int -> IntNat t
at so.hs:12:1-26
Expected type: IntNat t
Actual type: IntNat 0
• In the expression: IN 0 :: IntNat 0
In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
• Relevant bindings include
fromInt :: Int -> IntNat t (bound at so.hs:13:1)


This is because t and 0 are not the same - t is universal not existential. The offending lines are:



fromInt :: Int -> IntNat t
fromInt 0 = 0 :: IntNat 0


forall t. t == 0 is a hard proof to write






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%2f54027671%2fconstructing-a-nat-type%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









    2














    Because you defined a type synonym, and not a newtype, the meaning is quite different than what you seem to think. Roughly, IntNat _ will unify with Int and thus any other IntNat _.



    You can try this out by defining other intnats and see them unify in, say, a list:



    *Main> let five = 5 :: IntNat 99
    *Main> let xs = [four, five] :: [IntNat 42]
    *Main> :t xs
    xs :: [IntNat 42]


    or using a single intnat:



    *Main> let four' = four :: IntNat 1000
    *Main> :t four'
    four' :: IntNat 1000


    Instead consider using a newtype, such as newtype IntNat (n :: Nat) = IN Int. You'd get an error like:



    • Couldn't match type ‘t’ with ‘0’
    ‘t’ is a rigid type variable bound by
    the type signature for:
    fromInt :: forall (t :: Nat). Int -> IntNat t
    at so.hs:12:1-26
    Expected type: IntNat t
    Actual type: IntNat 0
    • In the expression: IN 0 :: IntNat 0
    In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
    • Relevant bindings include
    fromInt :: Int -> IntNat t (bound at so.hs:13:1)


    This is because t and 0 are not the same - t is universal not existential. The offending lines are:



    fromInt :: Int -> IntNat t
    fromInt 0 = 0 :: IntNat 0


    forall t. t == 0 is a hard proof to write






    share|improve this answer




























      2














      Because you defined a type synonym, and not a newtype, the meaning is quite different than what you seem to think. Roughly, IntNat _ will unify with Int and thus any other IntNat _.



      You can try this out by defining other intnats and see them unify in, say, a list:



      *Main> let five = 5 :: IntNat 99
      *Main> let xs = [four, five] :: [IntNat 42]
      *Main> :t xs
      xs :: [IntNat 42]


      or using a single intnat:



      *Main> let four' = four :: IntNat 1000
      *Main> :t four'
      four' :: IntNat 1000


      Instead consider using a newtype, such as newtype IntNat (n :: Nat) = IN Int. You'd get an error like:



      • Couldn't match type ‘t’ with ‘0’
      ‘t’ is a rigid type variable bound by
      the type signature for:
      fromInt :: forall (t :: Nat). Int -> IntNat t
      at so.hs:12:1-26
      Expected type: IntNat t
      Actual type: IntNat 0
      • In the expression: IN 0 :: IntNat 0
      In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
      • Relevant bindings include
      fromInt :: Int -> IntNat t (bound at so.hs:13:1)


      This is because t and 0 are not the same - t is universal not existential. The offending lines are:



      fromInt :: Int -> IntNat t
      fromInt 0 = 0 :: IntNat 0


      forall t. t == 0 is a hard proof to write






      share|improve this answer


























        2












        2








        2







        Because you defined a type synonym, and not a newtype, the meaning is quite different than what you seem to think. Roughly, IntNat _ will unify with Int and thus any other IntNat _.



        You can try this out by defining other intnats and see them unify in, say, a list:



        *Main> let five = 5 :: IntNat 99
        *Main> let xs = [four, five] :: [IntNat 42]
        *Main> :t xs
        xs :: [IntNat 42]


        or using a single intnat:



        *Main> let four' = four :: IntNat 1000
        *Main> :t four'
        four' :: IntNat 1000


        Instead consider using a newtype, such as newtype IntNat (n :: Nat) = IN Int. You'd get an error like:



        • Couldn't match type ‘t’ with ‘0’
        ‘t’ is a rigid type variable bound by
        the type signature for:
        fromInt :: forall (t :: Nat). Int -> IntNat t
        at so.hs:12:1-26
        Expected type: IntNat t
        Actual type: IntNat 0
        • In the expression: IN 0 :: IntNat 0
        In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
        • Relevant bindings include
        fromInt :: Int -> IntNat t (bound at so.hs:13:1)


        This is because t and 0 are not the same - t is universal not existential. The offending lines are:



        fromInt :: Int -> IntNat t
        fromInt 0 = 0 :: IntNat 0


        forall t. t == 0 is a hard proof to write






        share|improve this answer













        Because you defined a type synonym, and not a newtype, the meaning is quite different than what you seem to think. Roughly, IntNat _ will unify with Int and thus any other IntNat _.



        You can try this out by defining other intnats and see them unify in, say, a list:



        *Main> let five = 5 :: IntNat 99
        *Main> let xs = [four, five] :: [IntNat 42]
        *Main> :t xs
        xs :: [IntNat 42]


        or using a single intnat:



        *Main> let four' = four :: IntNat 1000
        *Main> :t four'
        four' :: IntNat 1000


        Instead consider using a newtype, such as newtype IntNat (n :: Nat) = IN Int. You'd get an error like:



        • Couldn't match type ‘t’ with ‘0’
        ‘t’ is a rigid type variable bound by
        the type signature for:
        fromInt :: forall (t :: Nat). Int -> IntNat t
        at so.hs:12:1-26
        Expected type: IntNat t
        Actual type: IntNat 0
        • In the expression: IN 0 :: IntNat 0
        In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
        • Relevant bindings include
        fromInt :: Int -> IntNat t (bound at so.hs:13:1)


        This is because t and 0 are not the same - t is universal not existential. The offending lines are:



        fromInt :: Int -> IntNat t
        fromInt 0 = 0 :: IntNat 0


        forall t. t == 0 is a hard proof to write







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 3 at 20:56









        Thomas M. DuBuissonThomas M. DuBuisson

        56.1k690154




        56.1k690154
































            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%2f54027671%2fconstructing-a-nat-type%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

            Mossoró

            Error while reading .h5 file using the rhdf5 package in R

            Pushsharp Apns notification error: 'InvalidToken'