Example of non-trivial functorsAre all Haskell functors endofunctors?Concrete example showing that monads are not closed under composition (with proof)?Composition of two functors is a functorSets, Functors and Eq confusionAre Functor instances unique?Lax monoidal functors with a different monoidal structureWhat does a nontrivial comonoid look like?Haskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines FunctorIs this property of a functor stronger than a monad?Why does the Functor class in Haskell not include a function on objects? Is `pure` that function?

Can a human be transformed into a Mind Flayer?

Rail-to-rail op-amp only reaches 90% of VCC, works sometimes, not everytime

Can the removal of a duty-free sales trolley result in a measurable reduction in emissions?

Was Self-modifying-code possible just using BASIC?

How to write a convincing religious myth?

Should I put programming books I wrote a few years ago on my resume?

What is the logic behind charging tax _in the form of money_ for owning property when the property does not produce money?

What would prevent chimeras from reproducing with each other?

2019 gold coins to share

Reference to understand the notation of orbital charts

Does a bank have to tell me if a check made out to me was cashed there?

Why was this person allowed to become Grand Maester?

How do we say "within a kilometer radius spherically"?

What is the best color to differentiate male and female?

Why did the World Bank set the global poverty line at $1.90?

Why is long-term living in Almost-Earth causing severe health problems?

The usage of kelvin in formulas

Section numbering in binary

How to befriend someone who doesn't like to talk?

Is it okay to have a sequel start immediately after the end of the first book?

Who is "He that flies" in Lord of the Rings?

Who won a Game of Bar Dice?

Is there a DSLR/mirorless camera with minimal options like a classic, simple SLR?

Why did Intel abandon unified CPU cache?



Example of non-trivial functors


Are all Haskell functors endofunctors?Concrete example showing that monads are not closed under composition (with proof)?Composition of two functors is a functorSets, Functors and Eq confusionAre Functor instances unique?Lax monoidal functors with a different monoidal structureWhat does a nontrivial comonoid look like?Haskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines FunctorIs this property of a functor stronger than a monad?Why does the Functor class in Haskell not include a function on objects? Is `pure` that function?






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








13















In Haskell, functors can almost always be derived, is there any case where a type is a functor and satisfies functor laws (such as fmap id == id) but cannot be derived according to a simple set of rules?



And what about Foldable, Traversable, Semigroup and others? Is there any non-trivial cases available?










share|improve this question
























  • You mean something like tuple when you don't know should you apply function to first value or second?

    – talex
    Jun 3 at 6:43











  • @talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

    – Jiaming Lu
    Jun 3 at 7:08






  • 2





    Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

    – michid
    Jun 3 at 7:20







  • 5





    Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

    – luqui
    Jun 3 at 7:27







  • 1





    @luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

    – dfeuer
    Jun 3 at 18:03

















13















In Haskell, functors can almost always be derived, is there any case where a type is a functor and satisfies functor laws (such as fmap id == id) but cannot be derived according to a simple set of rules?



And what about Foldable, Traversable, Semigroup and others? Is there any non-trivial cases available?










share|improve this question
























  • You mean something like tuple when you don't know should you apply function to first value or second?

    – talex
    Jun 3 at 6:43











  • @talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

    – Jiaming Lu
    Jun 3 at 7:08






  • 2





    Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

    – michid
    Jun 3 at 7:20







  • 5





    Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

    – luqui
    Jun 3 at 7:27







  • 1





    @luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

    – dfeuer
    Jun 3 at 18:03













13












13








13


1






In Haskell, functors can almost always be derived, is there any case where a type is a functor and satisfies functor laws (such as fmap id == id) but cannot be derived according to a simple set of rules?



And what about Foldable, Traversable, Semigroup and others? Is there any non-trivial cases available?










share|improve this question
















In Haskell, functors can almost always be derived, is there any case where a type is a functor and satisfies functor laws (such as fmap id == id) but cannot be derived according to a simple set of rules?



And what about Foldable, Traversable, Semigroup and others? Is there any non-trivial cases available?







haskell functor category-theory






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 3 at 11:34









Micha Wiedenmann

10.9k1465107




10.9k1465107










asked Jun 3 at 6:40









Jiaming LuJiaming Lu

663417




663417












  • You mean something like tuple when you don't know should you apply function to first value or second?

    – talex
    Jun 3 at 6:43











  • @talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

    – Jiaming Lu
    Jun 3 at 7:08






  • 2





    Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

    – michid
    Jun 3 at 7:20







  • 5





    Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

    – luqui
    Jun 3 at 7:27







  • 1





    @luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

    – dfeuer
    Jun 3 at 18:03

















  • You mean something like tuple when you don't know should you apply function to first value or second?

    – talex
    Jun 3 at 6:43











  • @talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

    – Jiaming Lu
    Jun 3 at 7:08






  • 2





    Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

    – michid
    Jun 3 at 7:20







  • 5





    Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

    – luqui
    Jun 3 at 7:27







  • 1





    @luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

    – dfeuer
    Jun 3 at 18:03
















You mean something like tuple when you don't know should you apply function to first value or second?

– talex
Jun 3 at 6:43





You mean something like tuple when you don't know should you apply function to first value or second?

– talex
Jun 3 at 6:43













@talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

– Jiaming Lu
Jun 3 at 7:08





@talex No, if you treat a tuple of (a, b) as a functor over b, then the result of fmap is (a, c), from which it's very clear which value shoud the function b -> c be applied to.

– Jiaming Lu
Jun 3 at 7:08




2




2





Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

– michid
Jun 3 at 7:20






Functor in Haskell can always be derived. Bartosz Milewski talks about this in his book *Category Theory for Programmers*[1]. I need to look up the exact reference and details myself but it has to do with functors in Haskell forming some sort of an algebra. [1] bartoszmilewski.com/2014/10/28/…

– michid
Jun 3 at 7:20





5




5





Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

– luqui
Jun 3 at 7:27






Foldable, Traversable, and Semigroup all have symmetries which allow them to be lawfully instantiated in multiple distinct ways, which is one sense of nontriviality at least

– luqui
Jun 3 at 7:27





1




1





@luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

– dfeuer
Jun 3 at 18:03





@luqui, if you use an Atkey-style indexed applicative to define a notion of traversable for type-aligned collections, then you should recover uniqueness.

– dfeuer
Jun 3 at 18:03












5 Answers
5






active

oldest

votes


















12














Here's kind of a fun argument I just stumbled on. (It's late so I wonder if it will be sensical tomorrow)



We can construct the type of proofs of SK reducibility as a GADT:



infixl 9 :%:
data Term = S | K | Term :%: Term

-- small step, you can get from t to t' in one step
data Red1 t t' where
Red1S :: Red1 (S :%: x :%: y :%: z) (x :%: z :%: (y :%: z))
...


Now let's make a type which hides its functorhood at the end of a reduction chain.



data Red t a where
RedStep :: Red1 t t' -> Red t' a -> Red t a
RedK :: a -> Red K a
RedS :: (a -> Bool) -> Red S a


Now Red t is a Functor if t normalizes to K, but not if it normalizes to S -- an undecidable problem. So perhaps you can still follow a "simple set of rules", but if you allow GADTs, the rules have to be powerful enough to compute anything.



(There is an alternative formulation which I find rather elegant, but maybe less demonstrative: if you drop the RedK constructor, then Red t is a Functor if and only if the type system can express that the reduction of t diverges -- and sometimes it diverges but you can't prove it, and my mind boggles about whether it's really a functor in that case or not)






share|improve this answer

























  • Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

    – dfeuer
    Jun 3 at 18:48











  • @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

    – luqui
    Jun 3 at 22:55






  • 1





    I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

    – dfeuer
    Jun 4 at 3:31


















9














Explicitly empty parametric types can be made into functors automatically:



data T a deriving Functor


However, implicitly empty ones can not:



import Data.Void
data T a = K a (a -> Void)
deriving Functor -- fails
-
error:
• Can't make a derived instance of ‘Functor T’:
Constructor ‘K’ must not use the type variable in a function argument
• In the data declaration for ‘T’
-


However,



instance Functor T where
fmap f (K x y) = absurd (y x)


is arguably a legal instance.



One could argue that, exploiting bottoms, one can find a counterexample to the functor laws for the instance above. In such case, however, I wonder if all the "standard" functor instances are actually lawful, even in the presence of bottoms. (Maybe they are?)






share|improve this answer




















  • 3





    Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

    – dfeuer
    Jun 3 at 18:17


















8














There are no non-trivial functors in the sense of the question. All functors can be derived mechanically as sums (Either) and products (Tuple) of the Identity and the Const functor. See the section about Functorial Algebraic Data Types for how this construction works in detail.



On a higher level of abstraction this works because Haskell's type form a Cartesian Closed Category where terminal objects, all products and all exponentials exist.






share|improve this answer
































    4














    It's a bit cheaty, but here we go. According to this then functor cannot be derived automatically when there's a constraint on the type, eg.



    data A a where
    A1 :: (Ord a) => a -> A a
    deriving instance Functor A -- doesn't work


    and indeed, if (say) we wrote a manual version, it wouldn't work either.



    instance Functor A where
    fmap f (A1 a) = A1 (f a) -- Can't deduce Ord for f a


    However, because all the algorithm's doing is checking that no constraint exists, we can introduce a typeclass of which every type is a member.



    class C c
    instance C c


    Now proceeding as above with C instead of Ord,



    data B b where
    B1 :: (C b) => b -> B b

    deriving instance Functor B -- doesn't work

    instance Functor B where
    fmap f (B1 b) = B1 (f b) -- does work!





    share|improve this answer






























      1














      There is a standard type in base called Compose defined like this:



      newtype Compose f g a = Compose getCompose :: f (g a) 


      The derived Functor instance is implemented this way:



      instance (Functor f, Functor g) => Functor (Compose f g) where
      fmap f (Compose v) = Compose (fmap (fmap f) v)


      But there is another perfectly lawful instance with different behavior:



      instance (Contravariant f, Contravariant g) => Functor (Compose f g) where
      fmap f (Compose v) = Compose (contramap (contramap f) v)


      To me, the fact that two distinct instances are available for Compose suggests to me that no set of rules can be automatically applied to cover all possible cases.






      share|improve this answer























      • Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

        – dfeuer
        Jun 4 at 9:35











      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%2f56422226%2fexample-of-non-trivial-functors%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      12














      Here's kind of a fun argument I just stumbled on. (It's late so I wonder if it will be sensical tomorrow)



      We can construct the type of proofs of SK reducibility as a GADT:



      infixl 9 :%:
      data Term = S | K | Term :%: Term

      -- small step, you can get from t to t' in one step
      data Red1 t t' where
      Red1S :: Red1 (S :%: x :%: y :%: z) (x :%: z :%: (y :%: z))
      ...


      Now let's make a type which hides its functorhood at the end of a reduction chain.



      data Red t a where
      RedStep :: Red1 t t' -> Red t' a -> Red t a
      RedK :: a -> Red K a
      RedS :: (a -> Bool) -> Red S a


      Now Red t is a Functor if t normalizes to K, but not if it normalizes to S -- an undecidable problem. So perhaps you can still follow a "simple set of rules", but if you allow GADTs, the rules have to be powerful enough to compute anything.



      (There is an alternative formulation which I find rather elegant, but maybe less demonstrative: if you drop the RedK constructor, then Red t is a Functor if and only if the type system can express that the reduction of t diverges -- and sometimes it diverges but you can't prove it, and my mind boggles about whether it's really a functor in that case or not)






      share|improve this answer

























      • Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

        – dfeuer
        Jun 3 at 18:48











      • @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

        – luqui
        Jun 3 at 22:55






      • 1





        I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

        – dfeuer
        Jun 4 at 3:31















      12














      Here's kind of a fun argument I just stumbled on. (It's late so I wonder if it will be sensical tomorrow)



      We can construct the type of proofs of SK reducibility as a GADT:



      infixl 9 :%:
      data Term = S | K | Term :%: Term

      -- small step, you can get from t to t' in one step
      data Red1 t t' where
      Red1S :: Red1 (S :%: x :%: y :%: z) (x :%: z :%: (y :%: z))
      ...


      Now let's make a type which hides its functorhood at the end of a reduction chain.



      data Red t a where
      RedStep :: Red1 t t' -> Red t' a -> Red t a
      RedK :: a -> Red K a
      RedS :: (a -> Bool) -> Red S a


      Now Red t is a Functor if t normalizes to K, but not if it normalizes to S -- an undecidable problem. So perhaps you can still follow a "simple set of rules", but if you allow GADTs, the rules have to be powerful enough to compute anything.



      (There is an alternative formulation which I find rather elegant, but maybe less demonstrative: if you drop the RedK constructor, then Red t is a Functor if and only if the type system can express that the reduction of t diverges -- and sometimes it diverges but you can't prove it, and my mind boggles about whether it's really a functor in that case or not)






      share|improve this answer

























      • Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

        – dfeuer
        Jun 3 at 18:48











      • @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

        – luqui
        Jun 3 at 22:55






      • 1





        I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

        – dfeuer
        Jun 4 at 3:31













      12












      12








      12







      Here's kind of a fun argument I just stumbled on. (It's late so I wonder if it will be sensical tomorrow)



      We can construct the type of proofs of SK reducibility as a GADT:



      infixl 9 :%:
      data Term = S | K | Term :%: Term

      -- small step, you can get from t to t' in one step
      data Red1 t t' where
      Red1S :: Red1 (S :%: x :%: y :%: z) (x :%: z :%: (y :%: z))
      ...


      Now let's make a type which hides its functorhood at the end of a reduction chain.



      data Red t a where
      RedStep :: Red1 t t' -> Red t' a -> Red t a
      RedK :: a -> Red K a
      RedS :: (a -> Bool) -> Red S a


      Now Red t is a Functor if t normalizes to K, but not if it normalizes to S -- an undecidable problem. So perhaps you can still follow a "simple set of rules", but if you allow GADTs, the rules have to be powerful enough to compute anything.



      (There is an alternative formulation which I find rather elegant, but maybe less demonstrative: if you drop the RedK constructor, then Red t is a Functor if and only if the type system can express that the reduction of t diverges -- and sometimes it diverges but you can't prove it, and my mind boggles about whether it's really a functor in that case or not)






      share|improve this answer















      Here's kind of a fun argument I just stumbled on. (It's late so I wonder if it will be sensical tomorrow)



      We can construct the type of proofs of SK reducibility as a GADT:



      infixl 9 :%:
      data Term = S | K | Term :%: Term

      -- small step, you can get from t to t' in one step
      data Red1 t t' where
      Red1S :: Red1 (S :%: x :%: y :%: z) (x :%: z :%: (y :%: z))
      ...


      Now let's make a type which hides its functorhood at the end of a reduction chain.



      data Red t a where
      RedStep :: Red1 t t' -> Red t' a -> Red t a
      RedK :: a -> Red K a
      RedS :: (a -> Bool) -> Red S a


      Now Red t is a Functor if t normalizes to K, but not if it normalizes to S -- an undecidable problem. So perhaps you can still follow a "simple set of rules", but if you allow GADTs, the rules have to be powerful enough to compute anything.



      (There is an alternative formulation which I find rather elegant, but maybe less demonstrative: if you drop the RedK constructor, then Red t is a Functor if and only if the type system can express that the reduction of t diverges -- and sometimes it diverges but you can't prove it, and my mind boggles about whether it's really a functor in that case or not)







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jun 4 at 4:01









      dfeuer

      34.4k350135




      34.4k350135










      answered Jun 3 at 7:54









      luquiluqui

      49.3k6116171




      49.3k6116171












      • Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

        – dfeuer
        Jun 3 at 18:48











      • @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

        – luqui
        Jun 3 at 22:55






      • 1





        I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

        – dfeuer
        Jun 4 at 3:31

















      • Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

        – dfeuer
        Jun 3 at 18:48











      • @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

        – luqui
        Jun 3 at 22:55






      • 1





        I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

        – dfeuer
        Jun 4 at 3:31
















      Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

      – dfeuer
      Jun 3 at 18:48





      Why might it not be a functor if reduction diverges? If you choose a deterministic reduction strategy in Red1, define data Blue t where BlueStep :: Red1 t t' -> Blue t' -> Blue t. (For a non-deterministic strategy, things get kind of ugly, because you have to separate out all the overlapping rules). Now you can consume Red t a alongside Blue t. At each step, the Red1 t t' in the Blue t proves that t is not S.

      – dfeuer
      Jun 3 at 18:48













      @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

      – luqui
      Jun 3 at 22:55





      @dfeuer, hm I'm not sure I'm following. Sure we can get that t is not S at each step, but in order to prove functorhood we need that at every step

      – luqui
      Jun 3 at 22:55




      1




      1





      I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

      – dfeuer
      Jun 4 at 3:31





      I haven't quite gotten there, but this gist sets up the framework I sketched, and goes much of the way toward expressing a proof of divergence for a particular example.

      – dfeuer
      Jun 4 at 3:31













      9














      Explicitly empty parametric types can be made into functors automatically:



      data T a deriving Functor


      However, implicitly empty ones can not:



      import Data.Void
      data T a = K a (a -> Void)
      deriving Functor -- fails
      -
      error:
      • Can't make a derived instance of ‘Functor T’:
      Constructor ‘K’ must not use the type variable in a function argument
      • In the data declaration for ‘T’
      -


      However,



      instance Functor T where
      fmap f (K x y) = absurd (y x)


      is arguably a legal instance.



      One could argue that, exploiting bottoms, one can find a counterexample to the functor laws for the instance above. In such case, however, I wonder if all the "standard" functor instances are actually lawful, even in the presence of bottoms. (Maybe they are?)






      share|improve this answer




















      • 3





        Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

        – dfeuer
        Jun 3 at 18:17















      9














      Explicitly empty parametric types can be made into functors automatically:



      data T a deriving Functor


      However, implicitly empty ones can not:



      import Data.Void
      data T a = K a (a -> Void)
      deriving Functor -- fails
      -
      error:
      • Can't make a derived instance of ‘Functor T’:
      Constructor ‘K’ must not use the type variable in a function argument
      • In the data declaration for ‘T’
      -


      However,



      instance Functor T where
      fmap f (K x y) = absurd (y x)


      is arguably a legal instance.



      One could argue that, exploiting bottoms, one can find a counterexample to the functor laws for the instance above. In such case, however, I wonder if all the "standard" functor instances are actually lawful, even in the presence of bottoms. (Maybe they are?)






      share|improve this answer




















      • 3





        Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

        – dfeuer
        Jun 3 at 18:17













      9












      9








      9







      Explicitly empty parametric types can be made into functors automatically:



      data T a deriving Functor


      However, implicitly empty ones can not:



      import Data.Void
      data T a = K a (a -> Void)
      deriving Functor -- fails
      -
      error:
      • Can't make a derived instance of ‘Functor T’:
      Constructor ‘K’ must not use the type variable in a function argument
      • In the data declaration for ‘T’
      -


      However,



      instance Functor T where
      fmap f (K x y) = absurd (y x)


      is arguably a legal instance.



      One could argue that, exploiting bottoms, one can find a counterexample to the functor laws for the instance above. In such case, however, I wonder if all the "standard" functor instances are actually lawful, even in the presence of bottoms. (Maybe they are?)






      share|improve this answer















      Explicitly empty parametric types can be made into functors automatically:



      data T a deriving Functor


      However, implicitly empty ones can not:



      import Data.Void
      data T a = K a (a -> Void)
      deriving Functor -- fails
      -
      error:
      • Can't make a derived instance of ‘Functor T’:
      Constructor ‘K’ must not use the type variable in a function argument
      • In the data declaration for ‘T’
      -


      However,



      instance Functor T where
      fmap f (K x y) = absurd (y x)


      is arguably a legal instance.



      One could argue that, exploiting bottoms, one can find a counterexample to the functor laws for the instance above. In such case, however, I wonder if all the "standard" functor instances are actually lawful, even in the presence of bottoms. (Maybe they are?)







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jun 3 at 10:22

























      answered Jun 3 at 10:05









      chichi

      79.4k288151




      79.4k288151







      • 3





        Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

        – dfeuer
        Jun 3 at 18:17












      • 3





        Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

        – dfeuer
        Jun 3 at 18:17







      3




      3





      Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

      – dfeuer
      Jun 3 at 18:17





      Most of the usual Functor instances are valid even with bottoms, I believe. Here's a simple type GHC can't derive Functor for: data Foo a = Foo (a -> Bool) !Void. There's another way contravariance can get in the way: newtype Bar f a = Bar (f a -> Bool). GHC can't derive the perfectly valid instance instance Contravariant f => Functor (Bar f) where fmap f (Bar g) = Bar (g . contramap f). The main trouble is that adding Contravariant into the deriving mix leads to be multiple potential instances (with incompatible constraints) for things like newtype Baz f g a = Baz (f (g a)).

      – dfeuer
      Jun 3 at 18:17











      8














      There are no non-trivial functors in the sense of the question. All functors can be derived mechanically as sums (Either) and products (Tuple) of the Identity and the Const functor. See the section about Functorial Algebraic Data Types for how this construction works in detail.



      On a higher level of abstraction this works because Haskell's type form a Cartesian Closed Category where terminal objects, all products and all exponentials exist.






      share|improve this answer





























        8














        There are no non-trivial functors in the sense of the question. All functors can be derived mechanically as sums (Either) and products (Tuple) of the Identity and the Const functor. See the section about Functorial Algebraic Data Types for how this construction works in detail.



        On a higher level of abstraction this works because Haskell's type form a Cartesian Closed Category where terminal objects, all products and all exponentials exist.






        share|improve this answer



























          8












          8








          8







          There are no non-trivial functors in the sense of the question. All functors can be derived mechanically as sums (Either) and products (Tuple) of the Identity and the Const functor. See the section about Functorial Algebraic Data Types for how this construction works in detail.



          On a higher level of abstraction this works because Haskell's type form a Cartesian Closed Category where terminal objects, all products and all exponentials exist.






          share|improve this answer















          There are no non-trivial functors in the sense of the question. All functors can be derived mechanically as sums (Either) and products (Tuple) of the Identity and the Const functor. See the section about Functorial Algebraic Data Types for how this construction works in detail.



          On a higher level of abstraction this works because Haskell's type form a Cartesian Closed Category where terminal objects, all products and all exponentials exist.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jun 4 at 9:37









          dfeuer

          34.4k350135




          34.4k350135










          answered Jun 3 at 7:49









          michidmichid

          6,01322039




          6,01322039





















              4














              It's a bit cheaty, but here we go. According to this then functor cannot be derived automatically when there's a constraint on the type, eg.



              data A a where
              A1 :: (Ord a) => a -> A a
              deriving instance Functor A -- doesn't work


              and indeed, if (say) we wrote a manual version, it wouldn't work either.



              instance Functor A where
              fmap f (A1 a) = A1 (f a) -- Can't deduce Ord for f a


              However, because all the algorithm's doing is checking that no constraint exists, we can introduce a typeclass of which every type is a member.



              class C c
              instance C c


              Now proceeding as above with C instead of Ord,



              data B b where
              B1 :: (C b) => b -> B b

              deriving instance Functor B -- doesn't work

              instance Functor B where
              fmap f (B1 b) = B1 (f b) -- does work!





              share|improve this answer



























                4














                It's a bit cheaty, but here we go. According to this then functor cannot be derived automatically when there's a constraint on the type, eg.



                data A a where
                A1 :: (Ord a) => a -> A a
                deriving instance Functor A -- doesn't work


                and indeed, if (say) we wrote a manual version, it wouldn't work either.



                instance Functor A where
                fmap f (A1 a) = A1 (f a) -- Can't deduce Ord for f a


                However, because all the algorithm's doing is checking that no constraint exists, we can introduce a typeclass of which every type is a member.



                class C c
                instance C c


                Now proceeding as above with C instead of Ord,



                data B b where
                B1 :: (C b) => b -> B b

                deriving instance Functor B -- doesn't work

                instance Functor B where
                fmap f (B1 b) = B1 (f b) -- does work!





                share|improve this answer

























                  4












                  4








                  4







                  It's a bit cheaty, but here we go. According to this then functor cannot be derived automatically when there's a constraint on the type, eg.



                  data A a where
                  A1 :: (Ord a) => a -> A a
                  deriving instance Functor A -- doesn't work


                  and indeed, if (say) we wrote a manual version, it wouldn't work either.



                  instance Functor A where
                  fmap f (A1 a) = A1 (f a) -- Can't deduce Ord for f a


                  However, because all the algorithm's doing is checking that no constraint exists, we can introduce a typeclass of which every type is a member.



                  class C c
                  instance C c


                  Now proceeding as above with C instead of Ord,



                  data B b where
                  B1 :: (C b) => b -> B b

                  deriving instance Functor B -- doesn't work

                  instance Functor B where
                  fmap f (B1 b) = B1 (f b) -- does work!





                  share|improve this answer













                  It's a bit cheaty, but here we go. According to this then functor cannot be derived automatically when there's a constraint on the type, eg.



                  data A a where
                  A1 :: (Ord a) => a -> A a
                  deriving instance Functor A -- doesn't work


                  and indeed, if (say) we wrote a manual version, it wouldn't work either.



                  instance Functor A where
                  fmap f (A1 a) = A1 (f a) -- Can't deduce Ord for f a


                  However, because all the algorithm's doing is checking that no constraint exists, we can introduce a typeclass of which every type is a member.



                  class C c
                  instance C c


                  Now proceeding as above with C instead of Ord,



                  data B b where
                  B1 :: (C b) => b -> B b

                  deriving instance Functor B -- doesn't work

                  instance Functor B where
                  fmap f (B1 b) = B1 (f b) -- does work!






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jun 3 at 7:59









                  moonGoosemoonGoose

                  1,163212




                  1,163212





















                      1














                      There is a standard type in base called Compose defined like this:



                      newtype Compose f g a = Compose getCompose :: f (g a) 


                      The derived Functor instance is implemented this way:



                      instance (Functor f, Functor g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (fmap (fmap f) v)


                      But there is another perfectly lawful instance with different behavior:



                      instance (Contravariant f, Contravariant g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (contramap (contramap f) v)


                      To me, the fact that two distinct instances are available for Compose suggests to me that no set of rules can be automatically applied to cover all possible cases.






                      share|improve this answer























                      • Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                        – dfeuer
                        Jun 4 at 9:35















                      1














                      There is a standard type in base called Compose defined like this:



                      newtype Compose f g a = Compose getCompose :: f (g a) 


                      The derived Functor instance is implemented this way:



                      instance (Functor f, Functor g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (fmap (fmap f) v)


                      But there is another perfectly lawful instance with different behavior:



                      instance (Contravariant f, Contravariant g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (contramap (contramap f) v)


                      To me, the fact that two distinct instances are available for Compose suggests to me that no set of rules can be automatically applied to cover all possible cases.






                      share|improve this answer























                      • Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                        – dfeuer
                        Jun 4 at 9:35













                      1












                      1








                      1







                      There is a standard type in base called Compose defined like this:



                      newtype Compose f g a = Compose getCompose :: f (g a) 


                      The derived Functor instance is implemented this way:



                      instance (Functor f, Functor g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (fmap (fmap f) v)


                      But there is another perfectly lawful instance with different behavior:



                      instance (Contravariant f, Contravariant g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (contramap (contramap f) v)


                      To me, the fact that two distinct instances are available for Compose suggests to me that no set of rules can be automatically applied to cover all possible cases.






                      share|improve this answer













                      There is a standard type in base called Compose defined like this:



                      newtype Compose f g a = Compose getCompose :: f (g a) 


                      The derived Functor instance is implemented this way:



                      instance (Functor f, Functor g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (fmap (fmap f) v)


                      But there is another perfectly lawful instance with different behavior:



                      instance (Contravariant f, Contravariant g) => Functor (Compose f g) where
                      fmap f (Compose v) = Compose (contramap (contramap f) v)


                      To me, the fact that two distinct instances are available for Compose suggests to me that no set of rules can be automatically applied to cover all possible cases.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Jun 4 at 3:14









                      Daniel WagnerDaniel Wagner

                      107k7164294




                      107k7164294












                      • Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                        – dfeuer
                        Jun 4 at 9:35

















                      • Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                        – dfeuer
                        Jun 4 at 9:35
















                      Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                      – dfeuer
                      Jun 4 at 9:35





                      Where both sets of constraints hold (i.e., when both f and g have phantom parameters), the instances have the same behavior. So I'd say this is about incompatible constraints rather than different behaviors.

                      – dfeuer
                      Jun 4 at 9:35

















                      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%2f56422226%2fexample-of-non-trivial-functors%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

                      Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

                      Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                      Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form