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.
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)