--------------------------------------------------------------------------------------------- |-- Module : Control.Functor.Yoneda-- Copyright : 2008 Edward Kmett-- License : BSD---- Maintainer : Edward Kmett <ekmett@gmail.com>-- Stability : experimental-- Portability : portable---- The Yoneda lemma can be realized as the Kan extension along Identity-- However, having this special instance allows us to define Yoneda f as a monad, -- comonad, etc. based on whatever properties the base functor has, without-- limiting ourselves to what Ran f f can manage.---- Performance wise, Yoneda may make your monad more efficient at handling a bunch of -- fmaps, while CoYoneda may do the same for a comonad assuming you require a greater than-- linear amount of time to fmap over your structure. You can apply each in either role-- but the asymptotics will probably not be in your favor.---------------------------------------------------------------------------------------------moduleControl.Functor.Yoneda(Yoneda(Yoneda,runYoneda),ranToYoneda,yonedaToRan,lowerYoneda,CoYoneda(CoYoneda),lanToCoYoneda,coYonedaToLan,liftCoYoneda)whereimportControl.ApplicativeimportControl.Comonad.HigherOrderimportControl.Comonad.CofreeimportControl.Comonad.ContextimportControl.Comonad.ReaderimportControl.Comonad.TransimportControl.Functor.ExtrasimportControl.Functor.KanExtensionimportControl.Functor.PointedimportControl.Functor.HigherOrderimportControl.Monad.IdentityimportControl.Monad.HigherOrderimportControl.Monad.FreeimportControl.Monad.TransimportControl.Monad.Reader.ClassimportControl.Monad.State.ClassimportControl.Monad.Writer.Class-- Yoneda ~ Ran IdentitynewtypeYonedafa=Yoneda{runYoneda::forallb.((a->b)->fb)}ranToYoneda::RanIdentityf:~>YonedafranToYonedar=Yoneda(\f->runRanr(Identity.f))yonedaToRan::Yonedaf:~>RanIdentityfyonedaToRany=Ran(\f->runYoneday(runIdentity.f))lowerYoneda::Yonedaf:~>flowerYonedam=runYonedamidinstanceFunctor(Yonedaf)wherefmapfm=Yoneda(\k->runYonedam(k.f))instancePointedf=>Pointed(Yonedaf)wherepointa=Yoneda(\f->point(fa))instanceApplicativef=>Applicative(Yonedaf)wherepurea=Yoneda(\f->pure(fa))m<*>n=Yoneda(\f->runYonedam(f.)<*>runYonedanid)instanceMonadf=>Monad(Yonedaf)wherereturna=Yoneda(\f->return(fa))m>>=k=Yoneda(\f->runYonedamid>>=\a->runYoneda(ka)f)instanceHFunctorYonedawhereffmap=fmaphfmapfy=Yoneda(f.runYoneday)-- f a -> Yoneda f a instanceHPointedYonedawherehreturna=Yoneda(\f->fmapfa)-- exists because Monad doesn't require Functor!instanceMonadTransYonedawherelifta=Yoneda(\f->liftMfa)instanceComonadTransYonedawherecolift=hreturn-- Yoneda f a -> f ainstanceHCopointedYonedawherehextractt=runYonedatidinstanceHMonadYonedawherehbindf=f.hextractinstanceHComonadYonedawherehextendf=hreturn.finstanceCopointedf=>Copointed(Yonedaf)whereextract=extract.hextractinstanceComonadf=>Comonad(Yonedaf)whereextendkm=Yoneda(\f->extend(f.k.hreturn)(hextractm))instanceMonadStateem=>MonadStatee(Yonedam)whereget=liftgetput=lift.putinstanceMonadReaderem=>MonadReadere(Yonedam)whereask=liftasklocalr=lift.localr.lowerYonedainstanceMonadWriterem=>MonadWritere(Yonedam)wheretell=lift.telllisten=lift.listen.fliprunYonedaidpass=lift.pass.lowerYonedainstanceMonadFreefm=>MonadFreef(Yonedam)whereinFree=lift.inFree.fmaplowerYonedainstanceRunMonadFreefm=>RunMonadFreef(Yonedam)wherecataFreelr=cataFreelr.lowerYonedainstanceComonadCofreefm=>ComonadCofreef(Yonedam)whereoutCofree=fmapcolift.outCofree.lowerYonedainstanceRunComonadCofreefm=>RunComonadCofreef(Yonedam)whereanaCofreelr=colift.anaCofreelrinstanceComonadContextem=>ComonadContexte(Yonedam)wheregetC=getC.lowerYonedamodifyCs=modifyCs.lowerYonedainstanceComonadReaderem=>ComonadReadere(Yonedam)whereaskC=askC.lowerYoneda-- | Left Kan Extensions-- CoYoneda ~ Lan IdentitydataCoYonedafa=forallb.CoYoneda(b->a)(fb)lanToCoYoneda::LanIdentityf:~>CoYonedaflanToCoYoneda(Lanfv)=CoYoneda(f.Identity)vcoYonedaToLan::CoYonedaf:~>LanIdentityfcoYonedaToLan(CoYonedafv)=Lan(f.runIdentity)vinstanceFunctor(CoYonedaf)wherefmapf(CoYonedagv)=CoYoneda(f.g)vinstancePointedf=>Pointed(CoYonedaf)wherepoint=hreturn.pointinstanceApplicativef=>Applicative(CoYonedaf)wherepure=hreturn.purem<*>n=CoYonedaid(hextractm<*>hextractn)instanceMonadm=>Monad(CoYonedam)wherereturn=CoYonedaid.returnCoYonedafv>>=k=CoYonedaid(v>>=(\(CoYonedaf'v')->liftMf'v').k.f)instanceHFunctorCoYonedawhereffmap=fmaphfmapf(CoYonedagv)=CoYonedag(fv)instanceHPointedCoYonedawherehreturn=CoYonedaidinstanceHMonadCoYonedawherehbindf=f.hextractinstanceHComonadCoYonedawherehextendf=hreturn.finstanceHCopointedCoYonedawherehextract(CoYonedafv)=fmapfvliftCoYoneda::f:~>CoYonedafliftCoYoneda=CoYonedaid-- | Just a conceptual nicety for monads since they aren't functors in Haskell. this is otherwise just hextractlowerCoYoneda::Monadf=>CoYonedaf:~>flowerCoYoneda(CoYonedafv)=liftMfvinstanceCopointedw=>Copointed(CoYonedaw)whereextract(CoYonedafv)=f(extractv)instanceComonadw=>Comonad(CoYonedaw)whereextendk(CoYonedafv)=CoYonedaid$extend(k.CoYonedaf)vinstanceMonadTransCoYonedawherelift=CoYonedaidinstanceComonadTransCoYonedawherecolift=CoYonedaid-- All the (Co)monadFoo CoYoneda instancesinstanceComonadCofreefm=>ComonadCofreef(CoYonedam)whereoutCofree=fmapcolift.outCofree.hextractinstanceRunComonadCofreefm=>RunComonadCofreef(CoYonedam)whereanaCofreelr=colift.anaCofreelrinstanceComonadContextem=>ComonadContexte(CoYonedam)wheregetC=getC.hextractmodifyCs=modifyCs.hextractinstanceComonadReaderem=>ComonadReadere(CoYonedam)whereaskC=askC.hextractinstanceMonadStateem=>MonadStatee(CoYonedam)whereget=liftgetput=lift.putinstanceMonadReaderem=>MonadReadere(CoYonedam)whereask=liftasklocalr=lift.localr.lowerCoYonedainstanceMonadWriterem=>MonadWritere(CoYonedam)wheretell=lift.telllisten=lift.listen.lowerCoYonedapass=lift.pass.lowerCoYonedainstanceMonadFreefm=>MonadFreef(CoYonedam)whereinFree=lift.inFree.fmaplowerCoYonedainstanceRunMonadFreefm=>RunMonadFreef(CoYonedam)wherecataFreelr=cataFreelr.lowerCoYoneda