Skip to content

Instantly share code, notes, and snippets.

@Icelandjack
Last active November 29, 2017 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Icelandjack/8839f1e16b60cadf40bf4da1a84fd9f6 to your computer and use it in GitHub Desktop.
Save Icelandjack/8839f1e16b60cadf40bf4da1a84fd9f6 to your computer and use it in GitHub Desktop.
Functor over type functions
{-# Language StandaloneDeriving, PatternSynonyms, GADTs, UndecidableInstances, ScopedTypeVariables, TemplateHaskell, TypeInType, TypeOperators, TypeFamilies, AllowAmbiguousTypes, InstanceSigs, TypeApplications #-}
import Data.Singletons
import Data.Singletons.Prelude.Base
import Data.Singletons.TH
import Data.Kind
import Control.Arrow ((***))
data Dup :: Type ~> Type
type instance Dup `Apply` a = (a, a)
-- A functor class that subsumes Prelude.Functor
class Functor' (f::Type ~> Type) where
fmap' :: (a -> a') -> (f@@a -> f@@a')
instance Functor' IdSym0 where
fmap' :: (a -> a') -> (a -> a')
fmap' = id
instance Functor' Dup where
fmap' :: (a -> a') -> ((a, a) -> (a', a'))
fmap' f = f *** f
instance (Functor' f, Functor' g) => Functor' (f :.$$$ g) where
fmap' :: (a -> a') -> (f@@(g@@a) -> f@@(g@@a'))
fmap' = fmap' @f . fmap' @g
newtype Applied f a = Applied (f @@ a)
deriving instance Show (f@@a) => Show (Applied f a)
instance Functor' f => Functor (Applied f) where
fmap :: (a -> a') -> (Applied f a -> Applied f a')
fmap f (Applied fa) = Applied (fmap' @f f fa)
instance Functor f => Functor' (TyCon1 f) where
fmap :: (a -> a') -> (f a -> f a')
fmap = fmap'
type Duped = Applied Dup
type Identity = Applied IdSym0
type Compose f g = Applied (TyCon1 f :.$$$ TyCon1 g)
----------------------------------------------------------------------
-- The ‘Data.Functor.*’ wrappers are special cases of these.
pattern Dup :: a -> a -> Duped a
pattern Dup a b = Applied (a, b)
pattern Identity :: a -> Identity a
pattern Identity a = Applied a
pattern Compose :: f (g a) -> Compose f g a
pattern Compose a = Applied a
-- >>> succ <$> Identity 'a'
-- Applied 'b'
-- >>> succ <$> Dup 'a' 'b'
-- Applid ('b', 'c')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment