Last active
September 16, 2021 00:43
-
-
Save MonoidMusician/30813fb645abe0cef9cc5ec6efe16b10 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE QuantifiedConstraints, MultiParamTypeClasses #-} | |
module CoercibleFunctor where | |
import Prelude () | |
import Data.Coerce (Coercible, coerce) | |
class (forall x y. Coercible x y => Coercible (f x) (f y)) => Functor f where | |
map :: forall a b. (a -> b) -> f a -> f b | |
newtype Identity a = Identity a | |
instance Functor Identity where | |
map f (Identity a) = Identity (f a) | |
newtype Wrapped f e = Wrapped (f e) | |
instance Functor f => Functor (Wrapped f) where | |
map f (Wrapped fa) = Wrapped (map f fa) | |
class (forall z. Functor (p z), forall w x y z. Coercible w x => Coercible y z => Coercible (p w y) (p x z)) => Bifunctor p where | |
bimap :: forall a b c d. (a -> b) -> (c -> d) -> p a c -> p b d | |
newtype Wrapped2 p a b = Wrapped2 (p a b) | |
instance Functor (p s) => Functor (Wrapped2 p s) where | |
map f (Wrapped2 psa) = Wrapped2 (map f psa) | |
instance Bifunctor p => Bifunctor (Wrapped2 p) where | |
bimap f g (Wrapped2 pac) = Wrapped2 (bimap f g pac) | |
class Coercible a b => Newtype a b | |
traverseC | |
:: forall f t a | |
. Coercible (f a) (f t) | |
=> Newtype t a | |
=> (a -> t) | |
-> (a -> f a) | |
-> t | |
-> f t | |
traverseC _ = coerce | |
traverseF | |
:: forall f t a | |
. Functor f -- implies Coercible (f a) (f t) | |
=> Newtype t a | |
=> (a -> t) | |
-> (a -> f a) | |
-> t | |
-> f t | |
traverseF = traverseC | |
data Either a b = Left a | Right b | |
instance Functor (Either a) where | |
map = bimap (\x -> x) | |
instance Bifunctor Either where | |
bimap f _ (Left a) = Left (f a) | |
bimap _ g (Right b) = Right (g b) | |
data Mu f = In (f (Mu f)) | |
-- This first attempt does not work because this "instance" is "missing" | |
-- (i.e. the magic compiler solving does not solve it like this) | |
-- instance (Coercible x y, Coercible (f a) (g b)) => Coercible (FreeF f x a) (FreeF g y b) | |
{- | |
data FreeF f a r = PureF a | RollF (f r) | |
instance Functor f => Functor (FreeF f a) where | |
map _ (PureF a) = PureF a | |
map g (RollF fr) = RollF (map g fr) | |
instance Functor f => Bifunctor (FreeF f) where | |
bimap f _ (PureF a) = PureF (f a) | |
bimap _ g (RollF fr) = RollF (map g fr) | |
newtype Free f a = Free (Mu (FreeF f a)) | |
unFree :: Free f a -> Mu (FreeF f a) | |
unFree = coerce | |
instance Functor f => Functor (Free f) where | |
map f (Free (In (PureF a))) = Free (In (PureF (f a))) | |
map f (Free (In (RollF fr))) = Free (In (RollF (map (\x -> unFree (map f (Free x))) fr))) | |
-} | |
-- As a next attempt, we go through `Either` so that we can use | |
-- the same transitivity trick as above, since `Either` is | |
-- `representational` in both arguments: | |
newtype FreeF f a r = FreeF (Either a (f r)) | |
-- The desired rule now holds: | |
-- since FreeF f x a ~ Either x (f a) ~ Either y (g b) ~ FreeF g y b | |
-- instance (Coercible x y, Coercible (f a) (g b)) => Coercible (FreeF f x a) (FreeF g y b) | |
testFreeF :: | |
Functor f => Coercible a b => Coercible c d => | |
FreeF f c a -> FreeF f d b | |
testFreeF = coerce | |
instance Functor f => Functor (FreeF f a) where | |
map f (FreeF x) = FreeF (map (map f) x) | |
instance Functor f => Bifunctor (FreeF f) where | |
bimap f _ (FreeF (Left a)) = FreeF (Left (f a)) | |
bimap _ g (FreeF (Right fr)) = FreeF (Right (map g fr)) | |
-- But now get stuck at `Mu`: | |
newtype Free f a = Free (Mu (FreeF f a)) | |
unFree :: Free f a -> Mu (FreeF f a) | |
unFree = coerce | |
{- | |
testFree :: | |
Functor f => Coercible a b => | |
Free f a -> Free f b | |
testFree = coerce | |
-} | |
{- | |
instance Functor f => Functor (Free f) where | |
map f (Free (In (FreeF (Left a)))) = Free (In (FreeF (Left (f a)))) | |
map f (Free (In (FreeF (Right fr)))) = Free (In (FreeF (Right (map (\x -> unFree (map f (Free x))) fr)))) | |
-} | |
-- This also gets stuck | |
data Freee f a = Pure a | Roll (f (Freee f a)) | |
{- | |
instance Functor f => Functor (Freee f) where | |
map f (Pure a) = Pure (f a) | |
map f (Roll fr) = Roll (map (map f) fr) | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment