{-# language GADTs #-} data C = C data A1 = A1 data A2 = A2 fa :: A1 -> Maybe A2 -> C fa = undefined data B1 = B1 data B2 = B2 fb :: B1 -> Maybe B2 -> C fb = undefined data Sum1 = InA1 A1 | InB1 B1 data Sum2 = InA2 A2 | InB2 B2 data Tag a where TagA :: Tag A2 TagB :: Tag B2 test :: Sum1 -> Maybe Sum2 -> Either String C test sum1 sum2 = case (sum1, sum2) of (InA1 a1, Nothing) -> Right $ fa a1 Nothing (InA1 a1, Just (InA2 a2)) -> Right $ fa a1 (Just a2) (InB1 b1, Nothing) -> Right $ fb b1 Nothing (InB1 b1, Just (InB2 b2)) -> Right $ fb b1 (Just b2) _ -> Left "..." main = undefined