The function f below, for a given type \'a\', takes a parameter of type \'c\'. For different types \'a\', \'c\' is restricted in different ways. Concretely, when \'a\' is any In
Here's a suggestion to solve a more general problem, not yours specifically (I need more detail yet first - I promise to check later). I'm writing it in case other people are searching for a solution to a similar problem to you, I certainly was in the past, before I discovered SO. SO is especially great when it helps you try a radically new approach.
I used to have the work habit:
Then I discovered the joys of type families (functional programming for types (hooray) - multi-parameter type classes are (a bit like) logic programming for types). My workflow changed to:
Introduce a type class including an associated type, i.e. replace
class MyProblematicClass a b | a -> b where
thing :: a -> b
thang :: b -> a -> b
with
class MyJustWorksClass a where
type Thing a :: * -- Thing a is a type (*), not a type constructor (* -> *)
thing :: a -> Thing a
thang :: Thing a -> a -> Thing a
Nervously add FlexibleInstances. Nothing goes wrong at all.
(MyJustWorksClass j,j~a)=>
instead of (MyJustWorksClass a)=>
or (Show t,t ~ Thing a,...)=>
instead of (Show (Thing a),...) =>
to help ghc out. (~
essentially means 'is the same type as')The reason "Nothing goes wrong at all" is that ghc calculates the type Thing a
using my type function Thang
rather than trying to deduce it using a merely a bunch of assertions that there's a function there and it ought to be able to work it out.
Give it a go! Read Fun with Type Functions before reading the manual!