Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE EmptyCase #-}{-# LANGUAGE GeneralizedNewtypeDeriving #-}{-# LANGUAGE StandaloneDeriving #-}{-# LANGUAGE Trustworthy #-}{-# LANGUAGE TypeOperators #-}------------------------------------------------------------------------------- |-- Module      :  Data.Functor.Contravariant-- Copyright   :  (C) 2007-2015 Edward Kmett-- License     :  BSD-style (see the file LICENSE)---- Maintainer  :  libraries@haskell.org-- Stability   :  provisional-- Portability :  portable---- 'Contravariant' functors, sometimes referred to colloquially as @Cofunctor@,-- even though the dual of a 'Functor' is just a 'Functor'. As with 'Functor'-- the definition of 'Contravariant' for a given ADT is unambiguous.---- @since 4.12.0.0----------------------------------------------------------------------------moduleData.Functor.Contravariant(-- * Contravariant FunctorsContravariant(..),phantom-- * Operators,(>$<),(>$$<),($<)-- * Predicates,Predicate(..)-- * Comparisons,Comparison(..),defaultComparison-- * Equivalence Relations,Equivalence(..),defaultEquivalence,comparisonEquivalence-- * Dual arrows,Op(..))whereimportControl.ApplicativeimportControl.CategoryimportData.Function(on)importData.Functor.ProductimportData.Functor.SumimportData.Functor.ComposeimportData.Monoid(Alt(..))importData.Semigroup(Semigroup(..))importData.ProxyimportGHC.GenericsimportPreludehiding((.),id)-- | The class of contravariant functors.---- Whereas in Haskell, one can think of a 'Functor' as containing or producing-- values, a contravariant functor is a functor that can be thought of as-- /consuming/ values.---- As an example, consider the type of predicate functions  @a -> Bool@. One-- such predicate might be @negative x = x < 0@, which-- classifies integers as to whether they are negative. However, given this-- predicate, we can re-use it in other situations, providing we have a way to-- map values /to/ integers. For instance, we can use the @negative@ predicate-- on a person's bank balance to work out if they are currently overdrawn:---- @-- newtype Predicate a = Predicate { getPredicate :: a -> Bool }---- instance Contravariant Predicate where--   contramap f (Predicate p) = Predicate (p . f)--                                          |   `- First, map the input...--                                          `----- then apply the predicate.---- overdrawn :: Predicate Person-- overdrawn = contramap personBankBalance negative-- @---- Any instance should be subject to the following laws:---- > contramap id = id-- > contramap f . contramap g = contramap (g . f)---- Note, that the second law follows from the free theorem of the type of-- 'contramap' and the first law, so you need only check that the former-- condition holds.classContravariantfwherecontramap::(a->b)->fb->fa-- | Replace all locations in the output with the same value.-- The default definition is @'contramap' . 'const'@, but this may be-- overridden with a more efficient version.(>$)::b->fb->fa(>$)=contramap.const-- | If 'f' is both 'Functor' and 'Contravariant' then by the time you factor-- in the laws of each of those classes, it can't actually use its argument in-- any meaningful capacity.---- This method is surprisingly useful. Where both instances exist and are-- lawful we have the following laws:---- @-- 'fmap' f ≡ 'phantom'-- 'contramap' f ≡ 'phantom'-- @phantom::(Functorf,Contravariantf)=>fa->fbphantomx=()<$x$<()infixl4>$,$<,>$<,>$$<-- | This is '>$' with its arguments flipped.($<)::Contravariantf=>fb->b->fa($<)=flip(>$)-- | This is an infix alias for 'contramap'.(>$<)::Contravariantf=>(a->b)->fb->fa(>$<)=contramap-- | This is an infix version of 'contramap' with the arguments flipped.(>$$<)::Contravariantf=>fb->(a->b)->fa(>$$<)=flipcontramapderivinginstanceContravariantf=>Contravariant(Altf)derivinginstanceContravariantf=>Contravariant(Rec1f)derivinginstanceContravariantf=>Contravariant(M1icf)instanceContravariantV1wherecontramap_x=casexofinstanceContravariantU1wherecontramap__=U1instanceContravariant(K1ic)wherecontramap_(K1c)=K1cinstance(Contravariantf,Contravariantg)=>Contravariant(f:*:g)wherecontramapf(xs:*:ys)=contramapfxs:*:contramapfysinstance(Functorf,Contravariantg)=>Contravariant(f:.:g)wherecontramapf(Comp1fg)=Comp1(fmap(contramapf)fg)instance(Contravariantf,Contravariantg)=>Contravariant(f:+:g)wherecontramapf(L1xs)=L1(contramapfxs)contramapf(R1ys)=R1(contramapfys)instance(Contravariantf,Contravariantg)=>Contravariant(Sumfg)wherecontramapf(InLxs)=InL(contramapfxs)contramapf(InRys)=InR(contramapfys)instance(Contravariantf,Contravariantg)=>Contravariant(Productfg)wherecontramapf(Pairab)=Pair(contramapfa)(contramapfb)instanceContravariant(Consta)wherecontramap_(Consta)=Constainstance(Functorf,Contravariantg)=>Contravariant(Composefg)wherecontramapf(Composefga)=Compose(fmap(contramapf)fga)instanceContravariantProxywherecontramap__=ProxynewtypePredicatea=Predicate{getPredicate::a->Bool}-- | A 'Predicate' is a 'Contravariant' 'Functor', because 'contramap' can-- apply its function argument to the input of the predicate.instanceContravariantPredicatewherecontramapfg=Predicate$getPredicateg.finstanceSemigroup(Predicatea)wherePredicatep<>Predicateq=Predicate$\a->pa&&qainstanceMonoid(Predicatea)wheremempty=Predicate$constTrue-- | Defines a total ordering on a type as per 'compare'.---- This condition is not checked by the types. You must ensure that the-- supplied values are valid total orderings yourself.newtypeComparisona=Comparison{getComparison::a->a->Ordering}derivinginstanceSemigroup(Comparisona)derivinginstanceMonoid(Comparisona)-- | A 'Comparison' is a 'Contravariant' 'Functor', because 'contramap' can-- apply its function argument to each input of the comparison function.instanceContravariantComparisonwherecontramapfg=Comparison$on(getComparisong)f-- | Compare using 'compare'.defaultComparison::Orda=>ComparisonadefaultComparison=Comparisoncompare-- | This data type represents an equivalence relation.---- Equivalence relations are expected to satisfy three laws:---- __Reflexivity__:---- @-- 'getEquivalence' f a a = True-- @---- __Symmetry__:---- @-- 'getEquivalence' f a b = 'getEquivalence' f b a-- @---- __Transitivity__:---- If @'getEquivalence' f a b@ and @'getEquivalence' f b c@ are both 'True'-- then so is @'getEquivalence' f a c@.---- The types alone do not enforce these laws, so you'll have to check them-- yourself.newtypeEquivalencea=Equivalence{getEquivalence::a->a->Bool}-- | Equivalence relations are 'Contravariant', because you can-- apply the contramapped function to each input to the equivalence-- relation.instanceContravariantEquivalencewherecontramapfg=Equivalence$on(getEquivalenceg)finstanceSemigroup(Equivalencea)whereEquivalencep<>Equivalenceq=Equivalence$\ab->pab&&qabinstanceMonoid(Equivalencea)wheremempty=Equivalence(\__->True)-- | Check for equivalence with '=='.---- Note: The instances for 'Double' and 'Float' violate reflexivity for @NaN@.defaultEquivalence::Eqa=>EquivalenceadefaultEquivalence=Equivalence(==)comparisonEquivalence::Comparisona->EquivalenceacomparisonEquivalence(Comparisonp)=Equivalence$\ab->pab==EQ-- | Dual function arrows.newtypeOpab=Op{getOp::b->a}derivinginstanceSemigroupa=>Semigroup(Opab)derivinginstanceMonoida=>Monoid(Opab)instanceCategoryOpwhereid=OpidOpf.Opg=Op(g.f)instanceContravariant(Opa)wherecontramapfg=Op(getOpg.f)instanceNuma=>Num(Opab)whereOpf+Opg=Op$\a->fa+gaOpf*Opg=Op$\a->fa*gaOpf-Opg=Op$\a->fa-gaabs(Opf)=Op$abs.fsignum(Opf)=Op$signum.ffromInteger=Op.const.fromIntegerinstanceFractionala=>Fractional(Opab)whereOpf/Opg=Op$\a->fa/garecip(Opf)=Op$recip.ffromRational=Op.const.fromRationalinstanceFloatinga=>Floating(Opab)wherepi=Op$constpiexp(Opf)=Op$exp.fsqrt(Opf)=Op$sqrt.flog(Opf)=Op$log.fsin(Opf)=Op$sin.ftan(Opf)=Op$tan.fcos(Opf)=Op$cos.fasin(Opf)=Op$asin.fatan(Opf)=Op$atan.facos(Opf)=Op$acos.fsinh(Opf)=Op$sinh.ftanh(Opf)=Op$tanh.fcosh(Opf)=Op$cosh.fasinh(Opf)=Op$asinh.fatanh(Opf)=Op$atanh.facosh(Opf)=Op$acosh.fOpf**Opg=Op$\a->fa**galogBase(Opf)(Opg)=Op$\a->logBase(fa)(ga)

[8]ページ先頭

©2009-2025 Movatter.jp