{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
UndecidableInstances, TypeFamilies #-}
class Appl fun arg t where
appl :: fun -> arg -> t
instance (a ~ a') => Appl (a -> b) a' b where
appl = id
instance {-# OVERLAPPING #-} Appl fun arg (b -> t) => Appl fun (b, arg) t where
appl f (n, rs) = appl f rs n
class Appr fun arg t where
appr :: fun -> arg -> t
instance (a ~ a') => Appr (a -> b) a' b where
appr f = f
instance {-# OVERLAPPING #-} (a ~ a', Appr fun arg t) => Appr (a -> fun) (a', arg) t where
appr f (a, x) = appr (f a) x
s/o to lyxia @ #haskell who wrote the appr half of this, which was enough to finally get me to comprehend all these messed-up recursive instances
(this generalizes the series of functions i enumerated here. the end goal is as always to unify all the
render* functions in this code, which is a more complicated step, but now one i'm a lot more confident that i can figure out.)(also as you might discover if you try to use this code, it requires type hints for everything: function, argument, and result. there might be some way for fundeps to fix that, but i haven't figured that out yet either. i don't know how annoying that would be in practice, since in practice i think the types would be pinned down by use elsewhere.)