Consider the code below:
t1 :: [Int] -> (Int,String)
t1 xs = (sum xs,show $ length xs)
t2 :: [Int] -> (Int,String)
t2 xs = (length xs, (\x -> '?') <$> xs)
t3 :: [Int] -> (Char,String)
t3 (x:xs) = ('Y',"1+" ++ (show $ length xs))
t3 [] = ('N',"empty")
These three functions are of a type that only partially changes — they are fully usable without the need to know the type of the first component of the tuple that they produce. This means that I can work with them without having to refer to this type:
fnListToStrs vs fs = (\x -> snd $ x vs) <$> fs
Loading these definitions into GHCi, all three functions work independently as an argument fnListToStrs, and indeed I can pass a list containing both t1 and t2, because they are of the same type:
*Imprec> fnListToStrs [1,2] [t1,t2]
["2","??"]
*Imprec> fnListToStrs [1,2] [t3]
["1+1"]
But I can not pass all 3 at the same time, although the type discrepancy is actually not related to the calculations performed:
*Imprec> fnListToStrs [1,2] [t1,t2]
["2","??"]
*Imprec> fnListToStrs [1,2] [t3]
["1+1"]
, - , , , fnListToStrs , :
fnListToStrs :: [Int] -> [forall a.[Int]->(a,String)] -> [String]
?