449 | | The `Bifunctor` class (born from the [http://hackage.haskell.org/package/bifunctors bifunctors] library) [https://ghc.haskell.org/trac/ghc/ticket/9682 was added] to `base` in GHC 7.10, and [https://ghc.haskell.org/trac/ghc/ticket/10448 there are plans] to add `Bifoldable` and `Bitraversable` to `base` in the future. All three classes could be derived in much the same way as their cousins `Functor`, `Foldable`, and `Traversable`. The existing algorithms would simply need to be adapted to accommodate two type parameters instead of one. |
450 | | |
451 | | The [https://github.com/ekmett/bifunctors/blob/8e975aead363802610dedccf414b884f9b39b1f4/src/Data/Bifunctor/TH.hs Data.Bifunctor.TH ] module from the `bifunctors` library demonstrates an implementation of the following proposal using Template Haskell. |
| 449 | There are more classes in `base` that we could derive! |
| 450 | |
| 451 | In particular, the `Bifunctor` class (born from the [http://hackage.haskell.org/package/bifunctors bifunctors] library) [https://ghc.haskell.org/trac/ghc/ticket/9682 was added] to `base` in GHC 7.10, and [https://ghc.haskell.org/trac/ghc/ticket/10448 there are plans] to add `Bifoldable` and `Bitraversable` to `base` in the future. All three classes could be derived in much the same way as their cousins `Functor`, `Foldable`, and `Traversable`. The existing algorithms would simply need to be adapted to accommodate two type parameters instead of one. The [https://github.com/ekmett/bifunctors/blob/c2e7717e1913dc53ad934b3d0ddd74d077b965c3/src/Data/Bifunctor/TH.hs Data.Bifunctor.TH] module from the `bifunctors` library demonstrates an implementation of the following proposal using Template Haskell. |
| 452 | |
| 453 | In GHC 8.0, higher-order versions of the `Eq`, `Ord`, `Read`, and `Show` typeclasses were added to `base` in the `Data.Functor.Classes` module (which originally lived in the `transformers` library). These classes are generalized to work over datatypes indexed by one type parameter (for `Eq1`, `Ord1`, `Read1`, and `Show1`) or by two type parameters (`Eq2`, `Ord2`, `Read2`, and `Show2`). Haskell programmers have been able to derive `Eq`, `Ord`, `Read`, and `Show` for a long time, so it wouldn't be hard at all to envision a deriving mechanism for `Eq1`, `Eq2`, and friends which takes advantage of tricks that `DeriveFunctor` uses. |
| 472 | |
| 473 | The typeclasses in `Data.Functor.Classes` are defined as follows: |
| 474 | |
| 475 | {{{#!hs |
| 476 | class Eq1 f where |
| 477 | liftEq :: (a -> b -> Bool) -> f a -> f b -> Bool |
| 478 | |
| 479 | class (Eq1 f) => Ord1 f where |
| 480 | liftCompare :: (a -> b -> Ordering) -> f a -> f b -> Ordering |
| 481 | |
| 482 | class Read1 f where |
| 483 | liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (f a) |
| 484 | liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [f a] |
| 485 | |
| 486 | class Show1 f where |
| 487 | liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> f a -> ShowS |
| 488 | liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [f a] -> ShowS |
| 489 | |
| 490 | class Eq2 f where |
| 491 | liftEq2 :: (a -> b -> Bool) -> (c -> d -> Bool) -> f a c -> f b d -> Bool |
| 492 | |
| 493 | class (Eq2 f) => Ord2 f where |
| 494 | liftCompare2 :: (a -> b -> Ordering) -> (c -> d -> Ordering) -> f a c -> f b d -> Ordering |
| 495 | |
| 496 | class Read2 f where |
| 497 | liftReadsPrec2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> Int -> ReadS (f a b) |
| 498 | liftReadList2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> ReadS [f a b] |
| 499 | |
| 500 | class Show2 f where |
| 501 | liftShowsPrec2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> Int -> f a b - > ShowS |
| 502 | liftShowList2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> [f a b] -> ShowS |
| 503 | }}} |