Coercing when Rep only equal after deeply evaluating type representations

103 Views Asked by At

I want to learn to use Deriving Via for more types. Currently a problem I'm often struggling with is when the generic representations are different, but would be equal if the conversion to type representations went deeper into nested types.

Simple example:

coerce @(Either () ()) @Bool

doesn't work, as Rec0 () :+: Rec0 () doesn't coerce with U1 :+: U1, even though :kind! Rep () gives U1, too.

More complex example

data LeafTree a = Leaf a | Branch [LeafTree a]

is isomorphic to Free [] a and it doesn't coerce for similar reasons. How I can I coerce between these types? I also know how to use DerivingVia with coercing between types with equal Rep1 if that helps here.

1

There are 1 best solutions below

0
Johannes Riecken On BEST ANSWER

Now with the iso-deriving package a monad instance could also be derived like this:

{-# LANGUAGE TypeOperators, FlexibleInstances, MultiParamTypeClasses, DeriveTraversable, DerivingVia #-}
import Control.Monad.Free
import Iso.Deriving

data LeafTree a = Leaf a | Branch [LeafTree a]
  deriving (Functor)
  deriving (Applicative, Monad) via Free [] `As1` LeafTree

instance Inject (Free [] a) (LeafTree a) where
  inj (Pure x ) = Leaf x
  inj (Free xs) = Branch (fmap inj xs)

instance Project (Free [] a) (LeafTree a) where
  prj (Leaf   x ) = Pure x
  prj (Branch xs) = Free (fmap prj xs)

instance Isomorphic (Free [] a) (LeafTree a)