You will need a type signature for run because you are using a template for GADT. GADT pattern matching requires type refinement and, as a rule, only works if there is a type signature.
But it is unclear what a type signature is. If the input value
a `Comb` b :: Stage xy
then you return (a, b) where
a :: Stage xb b :: Stage by
for the unknown b . This is an existential type screening. You can not write
run :: Stage xy -> (State xb, Stage by)
because it would mean that it should work for all b , but it only works for some (unknown) b .
Unfortunately, it is not clear why you want to write a function like run . Why make a couple? What do you want to do with this pair later? The Comb constructor is defined as combining two stages that have an unknown intermediate type, so this run version will work:
run :: Stage ab -> Stage ab run (a `Comb` b) = a `Comb` b run (FMap f) = FMap f `Comb` FMap id
Or you could define a more specific data type, allowing only a “pair” of two steps with an unknown intermediate type:
data PairStages ab where PairStages :: Stage ab -> Stage bc -> PairStages ac
And then:
run :: Stage ab -> PairStages ab run (a `Comb` b) = PairStages ab run (FMap f) = PairStages (FMap f) (FMap id)
But it still seems strange to me that run returns a pair. As I said, it is not clear what you want to do with the run result. It would seem more useful to have a run recursive function that actually somehow combines the results of starting components in the Comb case. For example, for example:
run :: Stage ab -> (a -> b) run (a `Comb` b) = run b . run a run (FMap f) = f