简体   繁体   中英

Equivalent to Functor or Foldable for higher-kinded types

Consider this code, using the Functor and Foldable typeclasses:

{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}

data Foo a = Foo (Maybe a) [a] deriving(Show, Functor, Foldable)

fmap (+1) (Foo (Just 1) [2,3,4]) -- result: Foo (Just 2) [3,4,5]
sum (Foo (Just 1) [2,3,4]) -- result: 10

Is there some analogous set of typeclasses that can operate on higher-kinded type parameters? For example:

data Bar a = Bar (a Int) (a Bool)

somethingLikeFmap :: forall t f g. SomethingLikeFunctor t => (forall a. f a -> g a) -> t f -> t g

somethingLikeAll :: forall t f. SomethingLikeFoldable t => (forall a. f a -> Bool) -> t f -> Bool

somethingLikeFmap listToMaybe (Bar [1,2,3] [False, True]) -- desired result: Bar (Just 1) (Just False)
somethingLikeAll null (Bar [1,2,3] [False, True]) -- desired result: False
somethingLikeAll null (Bar [] []) -- desired result: True

I suspect you are looking for rank2classes . For example:

{-# LANGUAGE FlexibleInstances, StandaloneDeriving, TemplateHaskell #-}

import Data.Maybe
import Data.Monoid
import qualified Rank2
import qualified Rank2.TH

data Bar a = Bar (a Int) (a Bool)
deriving instance Show (Bar Maybe)
Rank2.TH.deriveFunctor ''Bar
Rank2.TH.deriveFoldable ''Bar

main = do
    print $ Rank2.fmap listToMaybe (Bar [1,2,3] [False, True])
    print $ getAll (Rank2.foldMap (All . null) (Bar [1,2,3] [False, True]))
    print $ getAll (Rank2.foldMap (All . null) (Bar [] []))

EDIT: Or possibly mmorph , though I suspect rank2classes may prove more useful to you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM