I'm working on an applicative functor that contains a monoid to "view" the execution. However, sometimes I don't care about this part at all, so the choice of monoid is irrelevant as it will never be consumed. I've simplified what I have into:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a () where render = const ()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
is used to transform various a
s into a single b
. Merge
is a big simplification of my actual functor, but the point is it contains a type family/constraint and my intention of that is to specify exactly what Render
ers a Merge
requires.
Now, I might want to "run" the Merge
, but discard the view, which is akin to something like:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of () -> 5
But this will fail because:
Could not deduce
(Renderer a ())
arising from a use ofmerge
I chose ()
as my monoid because forall a
, we have an instance of Render a ()
. So if there was a way to say that Merge a
just means a collection Render
constraints then this would work fine. Of course, Merge a
is more general than that - it could add arbitrary constraints, which explains the compilation error.
Is there anyway to achieve what I want without changing the signature of runFoo
?
This might not scale if you have a lot of these cases, but this works:
class Renderer a () => Merge a where
...