Are there any valid definitions of this lambda statement in Haskell?











up vote
1
down vote

favorite
1












I have the following definition for a function in Haskell.



> q7 :: forall a. forall b. ((a -> b) -> a) -> a


I am challenged to either create a definition for it, or state why a definition does not exist. Here are my thoughts:



q7 takes in any types for a and b. The statement (a -> b) -> a would be implemented by taking two items and returning the latter. Now, if I go one tier further, I can just return this same "a" to fulfill ((a -> b) -> a) -> a. I see an issue in that a and b can be any type, so for each instance of a, could a be a different type? For example, could it be something like ((Int -> Bool) -> [Char]) -> Int? I probably murdered that syntax. If anyone has any hints or if anyone can confirm or deny my ideas, I would appreciate it greatly!










share|improve this question




















  • 4




    (a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
    – n.m.
    Nov 14 at 17:43










  • It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
    – chepner
    Nov 14 at 18:13








  • 1




    But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
    – chepner
    Nov 14 at 18:20

















up vote
1
down vote

favorite
1












I have the following definition for a function in Haskell.



> q7 :: forall a. forall b. ((a -> b) -> a) -> a


I am challenged to either create a definition for it, or state why a definition does not exist. Here are my thoughts:



q7 takes in any types for a and b. The statement (a -> b) -> a would be implemented by taking two items and returning the latter. Now, if I go one tier further, I can just return this same "a" to fulfill ((a -> b) -> a) -> a. I see an issue in that a and b can be any type, so for each instance of a, could a be a different type? For example, could it be something like ((Int -> Bool) -> [Char]) -> Int? I probably murdered that syntax. If anyone has any hints or if anyone can confirm or deny my ideas, I would appreciate it greatly!










share|improve this question




















  • 4




    (a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
    – n.m.
    Nov 14 at 17:43










  • It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
    – chepner
    Nov 14 at 18:13








  • 1




    But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
    – chepner
    Nov 14 at 18:20















up vote
1
down vote

favorite
1









up vote
1
down vote

favorite
1






1





I have the following definition for a function in Haskell.



> q7 :: forall a. forall b. ((a -> b) -> a) -> a


I am challenged to either create a definition for it, or state why a definition does not exist. Here are my thoughts:



q7 takes in any types for a and b. The statement (a -> b) -> a would be implemented by taking two items and returning the latter. Now, if I go one tier further, I can just return this same "a" to fulfill ((a -> b) -> a) -> a. I see an issue in that a and b can be any type, so for each instance of a, could a be a different type? For example, could it be something like ((Int -> Bool) -> [Char]) -> Int? I probably murdered that syntax. If anyone has any hints or if anyone can confirm or deny my ideas, I would appreciate it greatly!










share|improve this question















I have the following definition for a function in Haskell.



> q7 :: forall a. forall b. ((a -> b) -> a) -> a


I am challenged to either create a definition for it, or state why a definition does not exist. Here are my thoughts:



q7 takes in any types for a and b. The statement (a -> b) -> a would be implemented by taking two items and returning the latter. Now, if I go one tier further, I can just return this same "a" to fulfill ((a -> b) -> a) -> a. I see an issue in that a and b can be any type, so for each instance of a, could a be a different type? For example, could it be something like ((Int -> Bool) -> [Char]) -> Int? I probably murdered that syntax. If anyone has any hints or if anyone can confirm or deny my ideas, I would appreciate it greatly!







haskell typing lambda-calculus






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 at 2:25









duplode

22.8k44581




22.8k44581










asked Nov 14 at 17:34









Adrian Bernat

187




187








  • 4




    (a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
    – n.m.
    Nov 14 at 17:43










  • It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
    – chepner
    Nov 14 at 18:13








  • 1




    But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
    – chepner
    Nov 14 at 18:20
















  • 4




    (a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
    – n.m.
    Nov 14 at 17:43










  • It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
    – chepner
    Nov 14 at 18:13








  • 1




    But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
    – chepner
    Nov 14 at 18:20










4




4




(a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
– n.m.
Nov 14 at 17:43




(a -> b) -> a is a type of a function that takes a single argument (which is itself a function). There is no second item to return.
– n.m.
Nov 14 at 17:43












It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
– chepner
Nov 14 at 18:13






It's the same a throughout; ((int -> bool) -> [Char]) -> int isn't valid, because you can't unify int and [Char]. Quantification extends as far right as possible.
– chepner
Nov 14 at 18:13






1




1




But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
– chepner
Nov 14 at 18:20






But more to the point, @n.m. is saying that (a -> b) -> a is not the same as a -> b -> a; the -> operator is right-associative.
– chepner
Nov 14 at 18:20














3 Answers
3






active

oldest

votes

















up vote
5
down vote



accepted










It's impossible, except by using infinite recursion or runtime errors, so to fail to terminate.



We can prove that it is indeed impossible, exploiting some results from theoretical computer science. I don't know if there's an easier way to show that it's indeed impossible.



If there were a way to write a terminating program with that type, by the Curry-Howard correspondence, we would get that the logical formula ((a -> b) -> a) -> a (here, read -> as "implies") is a theorem of propositional intuitionistic logic.



Such formula is known as Peirce's Law, and is one of the key examples of a formula which is NOT provable in intuitionistic logic (by constrast, it is a theorem in classical logic).



As a reasonably easy way to prove that Peirce's law is not an intuitionistic theorem, one can run a decision procedure for propositional intuitionistic logic, and observe that it outputs "not a theorem". As such procedure, we could perform a search for a cut-free proof in Gentzen's LJ sequent calculus: in this way we only need to check a finite (and smallish) number of possible proofs, and observe that each attempt fails.






share|improve this answer























  • You can also go for the halting problem. See my answer, which goes through the excluded middle.
    – dfeuer
    Nov 14 at 23:18


















up vote
3
down vote













Suppose you have a function



pierce :: ((a -> b) -> a) -> a


Import



data Void


from Data.Void.



Now we get to play games. We can instantiate a and b in the type of pierce to whatever we like. Let's define



type A p = Either p (p -> Void)


and instantiate with



a ~ A p
b ~ Void


So



pierce :: ((A p -> Void) -> A p) -> A p


Let's write a helper:



noNegate :: forall p r. (A p -> Void) -> r
noNegate apv = absurd (n m)
where
m :: p -> Void
m = apv . Left

n :: (p -> Void) -> Void
n = apv . Right


Now we can go for the kill:



lem :: Either p (p -> Void)
lem = pierce noNegate


If this function existed, it would be very strange.



lem @Void = Right id
lem @() = Left ()
lem @Int = Left ... -- some integer, somehow


The behavior of this function seems so weird because it violates parametricity, which Haskell functions can't do, but things only get worse for it.



It's possible (but slightly annoying) to encode an arbitrary Turing machine as a Haskell type. And it's possible to design a type representing a proof that a particular Turing machine will halt (basically a type-indexed execution trace). Applying lem at such a trace type would solve the halting problem.





Thanks to Haskell's laziness, some "impossible" functions turn out to be useful, albeit partial. For example,



fix :: (a -> a) -> a


is formally absurd, since fix id claims to give you anything you want. pierce is not such a function. Let's try to write it:



pierce :: ((a -> b) -> a) -> a
pierce f = _


What must go on the right side? The only way to make an a is by applying f.



pierce f = f _


We must now supply something of type a -> b. We don't have one. We don't know what b is, so we can't pull the usual trick of starting with some b constructor to gain a beat. Nothing can ever improve our b. So the very best we can do is



pierce f = f (const undefined)


which doesn't look remotely useful.






share|improve this answer






























    up vote
    1
    down vote














    The statement (a -> b) -> a would be implemented by taking two items and returning the latter.




    You're confusing this with a -> b -> a (which can also be written a -> (b -> a). This is not the same.



    (a -> b) -> a is a function that takes a single argument and returns a value of type a. The argument has type a -> b, which means it is a function that takes a value of type a and returns a value of type b. This is not unlike (for example) the filter function:



    filter :: (a -> Bool) -> [a] -> [a]


    This takes two arguments, a predicate function of type a -> Bool and a list of type [a], and returns a new filtered [a] value by passing each list item to the predicate.






    I see an issue in that a and b can be any type, so for each instance of a, could a be a different type?




    No, if it could it would have a different name. a can be any type, but once you pick a type for a, every a in that type signature stands for that type. The b is a different letter, so it can be a different type from a.





    So, for your type signature ((a -> b) -> a) -> a, you would write a function that takes a single argument (another function) and returns an a. The argument function has type (a -> b) -> a, which means it takes a function of type a -> b as an argument and returns an a.



    func :: ((a -> b) -> a) -> a
    func f = ...


    The argument f, if called, would return an a that you could then return from func:



    func :: ((a -> b) -> a) -> a
    func f = f x
    where x :: a -> b
    x = ...


    However, to call f you would need to pass it a function a -> b, for all types a and b. As you don't have such a function available, and there's no way to write such a function in general, I think this is impossible to implement.






    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',
      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%2f53305859%2fare-there-any-valid-definitions-of-this-lambda-statement-in-haskell%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      5
      down vote



      accepted










      It's impossible, except by using infinite recursion or runtime errors, so to fail to terminate.



      We can prove that it is indeed impossible, exploiting some results from theoretical computer science. I don't know if there's an easier way to show that it's indeed impossible.



      If there were a way to write a terminating program with that type, by the Curry-Howard correspondence, we would get that the logical formula ((a -> b) -> a) -> a (here, read -> as "implies") is a theorem of propositional intuitionistic logic.



      Such formula is known as Peirce's Law, and is one of the key examples of a formula which is NOT provable in intuitionistic logic (by constrast, it is a theorem in classical logic).



      As a reasonably easy way to prove that Peirce's law is not an intuitionistic theorem, one can run a decision procedure for propositional intuitionistic logic, and observe that it outputs "not a theorem". As such procedure, we could perform a search for a cut-free proof in Gentzen's LJ sequent calculus: in this way we only need to check a finite (and smallish) number of possible proofs, and observe that each attempt fails.






      share|improve this answer























      • You can also go for the halting problem. See my answer, which goes through the excluded middle.
        – dfeuer
        Nov 14 at 23:18















      up vote
      5
      down vote



      accepted










      It's impossible, except by using infinite recursion or runtime errors, so to fail to terminate.



      We can prove that it is indeed impossible, exploiting some results from theoretical computer science. I don't know if there's an easier way to show that it's indeed impossible.



      If there were a way to write a terminating program with that type, by the Curry-Howard correspondence, we would get that the logical formula ((a -> b) -> a) -> a (here, read -> as "implies") is a theorem of propositional intuitionistic logic.



      Such formula is known as Peirce's Law, and is one of the key examples of a formula which is NOT provable in intuitionistic logic (by constrast, it is a theorem in classical logic).



      As a reasonably easy way to prove that Peirce's law is not an intuitionistic theorem, one can run a decision procedure for propositional intuitionistic logic, and observe that it outputs "not a theorem". As such procedure, we could perform a search for a cut-free proof in Gentzen's LJ sequent calculus: in this way we only need to check a finite (and smallish) number of possible proofs, and observe that each attempt fails.






      share|improve this answer























      • You can also go for the halting problem. See my answer, which goes through the excluded middle.
        – dfeuer
        Nov 14 at 23:18













      up vote
      5
      down vote



      accepted







      up vote
      5
      down vote



      accepted






      It's impossible, except by using infinite recursion or runtime errors, so to fail to terminate.



      We can prove that it is indeed impossible, exploiting some results from theoretical computer science. I don't know if there's an easier way to show that it's indeed impossible.



      If there were a way to write a terminating program with that type, by the Curry-Howard correspondence, we would get that the logical formula ((a -> b) -> a) -> a (here, read -> as "implies") is a theorem of propositional intuitionistic logic.



      Such formula is known as Peirce's Law, and is one of the key examples of a formula which is NOT provable in intuitionistic logic (by constrast, it is a theorem in classical logic).



      As a reasonably easy way to prove that Peirce's law is not an intuitionistic theorem, one can run a decision procedure for propositional intuitionistic logic, and observe that it outputs "not a theorem". As such procedure, we could perform a search for a cut-free proof in Gentzen's LJ sequent calculus: in this way we only need to check a finite (and smallish) number of possible proofs, and observe that each attempt fails.






      share|improve this answer














      It's impossible, except by using infinite recursion or runtime errors, so to fail to terminate.



      We can prove that it is indeed impossible, exploiting some results from theoretical computer science. I don't know if there's an easier way to show that it's indeed impossible.



      If there were a way to write a terminating program with that type, by the Curry-Howard correspondence, we would get that the logical formula ((a -> b) -> a) -> a (here, read -> as "implies") is a theorem of propositional intuitionistic logic.



      Such formula is known as Peirce's Law, and is one of the key examples of a formula which is NOT provable in intuitionistic logic (by constrast, it is a theorem in classical logic).



      As a reasonably easy way to prove that Peirce's law is not an intuitionistic theorem, one can run a decision procedure for propositional intuitionistic logic, and observe that it outputs "not a theorem". As such procedure, we could perform a search for a cut-free proof in Gentzen's LJ sequent calculus: in this way we only need to check a finite (and smallish) number of possible proofs, and observe that each attempt fails.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 14 at 22:22

























      answered Nov 14 at 19:39









      chi

      72.4k280134




      72.4k280134












      • You can also go for the halting problem. See my answer, which goes through the excluded middle.
        – dfeuer
        Nov 14 at 23:18


















      • You can also go for the halting problem. See my answer, which goes through the excluded middle.
        – dfeuer
        Nov 14 at 23:18
















      You can also go for the halting problem. See my answer, which goes through the excluded middle.
      – dfeuer
      Nov 14 at 23:18




      You can also go for the halting problem. See my answer, which goes through the excluded middle.
      – dfeuer
      Nov 14 at 23:18












      up vote
      3
      down vote













      Suppose you have a function



      pierce :: ((a -> b) -> a) -> a


      Import



      data Void


      from Data.Void.



      Now we get to play games. We can instantiate a and b in the type of pierce to whatever we like. Let's define



      type A p = Either p (p -> Void)


      and instantiate with



      a ~ A p
      b ~ Void


      So



      pierce :: ((A p -> Void) -> A p) -> A p


      Let's write a helper:



      noNegate :: forall p r. (A p -> Void) -> r
      noNegate apv = absurd (n m)
      where
      m :: p -> Void
      m = apv . Left

      n :: (p -> Void) -> Void
      n = apv . Right


      Now we can go for the kill:



      lem :: Either p (p -> Void)
      lem = pierce noNegate


      If this function existed, it would be very strange.



      lem @Void = Right id
      lem @() = Left ()
      lem @Int = Left ... -- some integer, somehow


      The behavior of this function seems so weird because it violates parametricity, which Haskell functions can't do, but things only get worse for it.



      It's possible (but slightly annoying) to encode an arbitrary Turing machine as a Haskell type. And it's possible to design a type representing a proof that a particular Turing machine will halt (basically a type-indexed execution trace). Applying lem at such a trace type would solve the halting problem.





      Thanks to Haskell's laziness, some "impossible" functions turn out to be useful, albeit partial. For example,



      fix :: (a -> a) -> a


      is formally absurd, since fix id claims to give you anything you want. pierce is not such a function. Let's try to write it:



      pierce :: ((a -> b) -> a) -> a
      pierce f = _


      What must go on the right side? The only way to make an a is by applying f.



      pierce f = f _


      We must now supply something of type a -> b. We don't have one. We don't know what b is, so we can't pull the usual trick of starting with some b constructor to gain a beat. Nothing can ever improve our b. So the very best we can do is



      pierce f = f (const undefined)


      which doesn't look remotely useful.






      share|improve this answer



























        up vote
        3
        down vote













        Suppose you have a function



        pierce :: ((a -> b) -> a) -> a


        Import



        data Void


        from Data.Void.



        Now we get to play games. We can instantiate a and b in the type of pierce to whatever we like. Let's define



        type A p = Either p (p -> Void)


        and instantiate with



        a ~ A p
        b ~ Void


        So



        pierce :: ((A p -> Void) -> A p) -> A p


        Let's write a helper:



        noNegate :: forall p r. (A p -> Void) -> r
        noNegate apv = absurd (n m)
        where
        m :: p -> Void
        m = apv . Left

        n :: (p -> Void) -> Void
        n = apv . Right


        Now we can go for the kill:



        lem :: Either p (p -> Void)
        lem = pierce noNegate


        If this function existed, it would be very strange.



        lem @Void = Right id
        lem @() = Left ()
        lem @Int = Left ... -- some integer, somehow


        The behavior of this function seems so weird because it violates parametricity, which Haskell functions can't do, but things only get worse for it.



        It's possible (but slightly annoying) to encode an arbitrary Turing machine as a Haskell type. And it's possible to design a type representing a proof that a particular Turing machine will halt (basically a type-indexed execution trace). Applying lem at such a trace type would solve the halting problem.





        Thanks to Haskell's laziness, some "impossible" functions turn out to be useful, albeit partial. For example,



        fix :: (a -> a) -> a


        is formally absurd, since fix id claims to give you anything you want. pierce is not such a function. Let's try to write it:



        pierce :: ((a -> b) -> a) -> a
        pierce f = _


        What must go on the right side? The only way to make an a is by applying f.



        pierce f = f _


        We must now supply something of type a -> b. We don't have one. We don't know what b is, so we can't pull the usual trick of starting with some b constructor to gain a beat. Nothing can ever improve our b. So the very best we can do is



        pierce f = f (const undefined)


        which doesn't look remotely useful.






        share|improve this answer

























          up vote
          3
          down vote










          up vote
          3
          down vote









          Suppose you have a function



          pierce :: ((a -> b) -> a) -> a


          Import



          data Void


          from Data.Void.



          Now we get to play games. We can instantiate a and b in the type of pierce to whatever we like. Let's define



          type A p = Either p (p -> Void)


          and instantiate with



          a ~ A p
          b ~ Void


          So



          pierce :: ((A p -> Void) -> A p) -> A p


          Let's write a helper:



          noNegate :: forall p r. (A p -> Void) -> r
          noNegate apv = absurd (n m)
          where
          m :: p -> Void
          m = apv . Left

          n :: (p -> Void) -> Void
          n = apv . Right


          Now we can go for the kill:



          lem :: Either p (p -> Void)
          lem = pierce noNegate


          If this function existed, it would be very strange.



          lem @Void = Right id
          lem @() = Left ()
          lem @Int = Left ... -- some integer, somehow


          The behavior of this function seems so weird because it violates parametricity, which Haskell functions can't do, but things only get worse for it.



          It's possible (but slightly annoying) to encode an arbitrary Turing machine as a Haskell type. And it's possible to design a type representing a proof that a particular Turing machine will halt (basically a type-indexed execution trace). Applying lem at such a trace type would solve the halting problem.





          Thanks to Haskell's laziness, some "impossible" functions turn out to be useful, albeit partial. For example,



          fix :: (a -> a) -> a


          is formally absurd, since fix id claims to give you anything you want. pierce is not such a function. Let's try to write it:



          pierce :: ((a -> b) -> a) -> a
          pierce f = _


          What must go on the right side? The only way to make an a is by applying f.



          pierce f = f _


          We must now supply something of type a -> b. We don't have one. We don't know what b is, so we can't pull the usual trick of starting with some b constructor to gain a beat. Nothing can ever improve our b. So the very best we can do is



          pierce f = f (const undefined)


          which doesn't look remotely useful.






          share|improve this answer














          Suppose you have a function



          pierce :: ((a -> b) -> a) -> a


          Import



          data Void


          from Data.Void.



          Now we get to play games. We can instantiate a and b in the type of pierce to whatever we like. Let's define



          type A p = Either p (p -> Void)


          and instantiate with



          a ~ A p
          b ~ Void


          So



          pierce :: ((A p -> Void) -> A p) -> A p


          Let's write a helper:



          noNegate :: forall p r. (A p -> Void) -> r
          noNegate apv = absurd (n m)
          where
          m :: p -> Void
          m = apv . Left

          n :: (p -> Void) -> Void
          n = apv . Right


          Now we can go for the kill:



          lem :: Either p (p -> Void)
          lem = pierce noNegate


          If this function existed, it would be very strange.



          lem @Void = Right id
          lem @() = Left ()
          lem @Int = Left ... -- some integer, somehow


          The behavior of this function seems so weird because it violates parametricity, which Haskell functions can't do, but things only get worse for it.



          It's possible (but slightly annoying) to encode an arbitrary Turing machine as a Haskell type. And it's possible to design a type representing a proof that a particular Turing machine will halt (basically a type-indexed execution trace). Applying lem at such a trace type would solve the halting problem.





          Thanks to Haskell's laziness, some "impossible" functions turn out to be useful, albeit partial. For example,



          fix :: (a -> a) -> a


          is formally absurd, since fix id claims to give you anything you want. pierce is not such a function. Let's try to write it:



          pierce :: ((a -> b) -> a) -> a
          pierce f = _


          What must go on the right side? The only way to make an a is by applying f.



          pierce f = f _


          We must now supply something of type a -> b. We don't have one. We don't know what b is, so we can't pull the usual trick of starting with some b constructor to gain a beat. Nothing can ever improve our b. So the very best we can do is



          pierce f = f (const undefined)


          which doesn't look remotely useful.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 at 0:35

























          answered Nov 14 at 22:55









          dfeuer

          32.1k347126




          32.1k347126






















              up vote
              1
              down vote














              The statement (a -> b) -> a would be implemented by taking two items and returning the latter.




              You're confusing this with a -> b -> a (which can also be written a -> (b -> a). This is not the same.



              (a -> b) -> a is a function that takes a single argument and returns a value of type a. The argument has type a -> b, which means it is a function that takes a value of type a and returns a value of type b. This is not unlike (for example) the filter function:



              filter :: (a -> Bool) -> [a] -> [a]


              This takes two arguments, a predicate function of type a -> Bool and a list of type [a], and returns a new filtered [a] value by passing each list item to the predicate.






              I see an issue in that a and b can be any type, so for each instance of a, could a be a different type?




              No, if it could it would have a different name. a can be any type, but once you pick a type for a, every a in that type signature stands for that type. The b is a different letter, so it can be a different type from a.





              So, for your type signature ((a -> b) -> a) -> a, you would write a function that takes a single argument (another function) and returns an a. The argument function has type (a -> b) -> a, which means it takes a function of type a -> b as an argument and returns an a.



              func :: ((a -> b) -> a) -> a
              func f = ...


              The argument f, if called, would return an a that you could then return from func:



              func :: ((a -> b) -> a) -> a
              func f = f x
              where x :: a -> b
              x = ...


              However, to call f you would need to pass it a function a -> b, for all types a and b. As you don't have such a function available, and there's no way to write such a function in general, I think this is impossible to implement.






              share|improve this answer



























                up vote
                1
                down vote














                The statement (a -> b) -> a would be implemented by taking two items and returning the latter.




                You're confusing this with a -> b -> a (which can also be written a -> (b -> a). This is not the same.



                (a -> b) -> a is a function that takes a single argument and returns a value of type a. The argument has type a -> b, which means it is a function that takes a value of type a and returns a value of type b. This is not unlike (for example) the filter function:



                filter :: (a -> Bool) -> [a] -> [a]


                This takes two arguments, a predicate function of type a -> Bool and a list of type [a], and returns a new filtered [a] value by passing each list item to the predicate.






                I see an issue in that a and b can be any type, so for each instance of a, could a be a different type?




                No, if it could it would have a different name. a can be any type, but once you pick a type for a, every a in that type signature stands for that type. The b is a different letter, so it can be a different type from a.





                So, for your type signature ((a -> b) -> a) -> a, you would write a function that takes a single argument (another function) and returns an a. The argument function has type (a -> b) -> a, which means it takes a function of type a -> b as an argument and returns an a.



                func :: ((a -> b) -> a) -> a
                func f = ...


                The argument f, if called, would return an a that you could then return from func:



                func :: ((a -> b) -> a) -> a
                func f = f x
                where x :: a -> b
                x = ...


                However, to call f you would need to pass it a function a -> b, for all types a and b. As you don't have such a function available, and there's no way to write such a function in general, I think this is impossible to implement.






                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote










                  The statement (a -> b) -> a would be implemented by taking two items and returning the latter.




                  You're confusing this with a -> b -> a (which can also be written a -> (b -> a). This is not the same.



                  (a -> b) -> a is a function that takes a single argument and returns a value of type a. The argument has type a -> b, which means it is a function that takes a value of type a and returns a value of type b. This is not unlike (for example) the filter function:



                  filter :: (a -> Bool) -> [a] -> [a]


                  This takes two arguments, a predicate function of type a -> Bool and a list of type [a], and returns a new filtered [a] value by passing each list item to the predicate.






                  I see an issue in that a and b can be any type, so for each instance of a, could a be a different type?




                  No, if it could it would have a different name. a can be any type, but once you pick a type for a, every a in that type signature stands for that type. The b is a different letter, so it can be a different type from a.





                  So, for your type signature ((a -> b) -> a) -> a, you would write a function that takes a single argument (another function) and returns an a. The argument function has type (a -> b) -> a, which means it takes a function of type a -> b as an argument and returns an a.



                  func :: ((a -> b) -> a) -> a
                  func f = ...


                  The argument f, if called, would return an a that you could then return from func:



                  func :: ((a -> b) -> a) -> a
                  func f = f x
                  where x :: a -> b
                  x = ...


                  However, to call f you would need to pass it a function a -> b, for all types a and b. As you don't have such a function available, and there's no way to write such a function in general, I think this is impossible to implement.






                  share|improve this answer















                  The statement (a -> b) -> a would be implemented by taking two items and returning the latter.




                  You're confusing this with a -> b -> a (which can also be written a -> (b -> a). This is not the same.



                  (a -> b) -> a is a function that takes a single argument and returns a value of type a. The argument has type a -> b, which means it is a function that takes a value of type a and returns a value of type b. This is not unlike (for example) the filter function:



                  filter :: (a -> Bool) -> [a] -> [a]


                  This takes two arguments, a predicate function of type a -> Bool and a list of type [a], and returns a new filtered [a] value by passing each list item to the predicate.






                  I see an issue in that a and b can be any type, so for each instance of a, could a be a different type?




                  No, if it could it would have a different name. a can be any type, but once you pick a type for a, every a in that type signature stands for that type. The b is a different letter, so it can be a different type from a.





                  So, for your type signature ((a -> b) -> a) -> a, you would write a function that takes a single argument (another function) and returns an a. The argument function has type (a -> b) -> a, which means it takes a function of type a -> b as an argument and returns an a.



                  func :: ((a -> b) -> a) -> a
                  func f = ...


                  The argument f, if called, would return an a that you could then return from func:



                  func :: ((a -> b) -> a) -> a
                  func f = f x
                  where x :: a -> b
                  x = ...


                  However, to call f you would need to pass it a function a -> b, for all types a and b. As you don't have such a function available, and there's no way to write such a function in general, I think this is impossible to implement.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 14 at 19:56

























                  answered Nov 14 at 19:44









                  DarthFennec

                  1,271711




                  1,271711






























                      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.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • 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%2f53305859%2fare-there-any-valid-definitions-of-this-lambda-statement-in-haskell%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

                      Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                      ComboBox Display Member on multiple fields

                      Is it possible to collect Nectar points via Trainline?