How can I mentally infer the type of the composition of these functions?

```    a :: [[Char]] -> [([Char],Int,Int)]
b :: [Int] -> [(Int,Bool)]
c :: [([Char],Int,Int)] -> ([Char],Int)
d :: [(Int,Bool)] -> [[Char]]```

That is, what is the type of:

`    c . a . d . b`

The first thing I’d do is rename the tricky types:

```    a :: [String] -> [(String,Int,Int)]
b :: [Int] -> [(Int,Bool)]
c :: [(String,Int,Int)] -> (String,Int)
d :: [(Int,Bool)] -> [String]```

and then introduce some type synonyms:

```    type A = [String]
type B = [(String,Int,Int)]
type C = [(Int,Bool)]```

Now we can rename the complex types to a more symbolic form:

```    a :: A -> B
b :: [Int] -> C
c :: B -> (String,Int)
d :: C -> A```

and now we can see how to combine the pieces. It’s a little jigsaw puzzle!

`    b :: [Int] -> C`

so there’s only one option to compose with b, namely

```    b :: [Int] -> C
d :: C -> A```

composing these, and we hide the intermediate result:

`    d . b :: [Int] -> A`

now, we need something that takes an A:

`    a :: A -> B`

So the result of something composed with a, will be a value of type B:

`    a . d . b :: [Int] -> B`

and finally, something that takes a B:

`    c :: B -> (String,Int)`

`    c . a . d . b :: [Int] -> (String,Int)`

and we’re done!