Tipo verificado gráfico decomponível em Haskell

Digamos que estou criando um pipeline de dados que processará arquivos de texto. Eu tenho os seguintes tipos e funções:

data A = A deriving (Show, Typeable)
data B = B deriving (Show, Typeable)
data C = C deriving (Show, Typeable)
data D = D deriving (Show, Typeable)

step1 :: A -> B
step2 :: B -> C
step3 :: C -> D

Para cada uma das funções da etapa {1..3} abaixo, eu gostaria de poder produzir um novo arquivo a partir de um arquivo existente, fazendo algo como:

interact (lines . map (show . step . read) . unlines)

Eu quero então poder organizá-los em um gráfico (para que as funções possam ter várias entradas) para obter o seguinte:

Eu posso atravessar a estrutura de dados para dizer quais funções fornecem entradas às quais outras

A estrutura de dados irá digitar a verificação em tempo de compilação, para que qualquer acordo inválido lance um erro de tipo.

Eu sei como fazer 1 sem 2 (dar-lhes uma typeclass comum), e eu sei como fazer 2 sem 1 (apenas use (.)), Mas não sei como fazer as duas coisas ao mesmo tempo. Alguma ideia? TIA.

Atualizar

A resposta de AndrewC é bem visível e me leva a maior parte do caminho, já que posso construir o gráfico de metadados (nomes) usando um mapa e digitá-lo separadamente ao mesmo tempo, mas também preciso de algum polimorfismo flexível. O exemplo abaixo resolve isso, mas com duas advertências sérias:

Eu não sou forçado a ser exaustivo na correspondência de padrões no step4.É tedioso; pode haver dezenas desses tipos polimórficos estilo "BorC", que não fazem nada exceto ativar o polimorfismo, e nem mesmo com muita segurança (veja 1). Eu tentei combinar o padrão em membros de uma classe de tipo (Step4Input com instâncias paraB eC) mas isso não funcionou (diziaCouldn't match type B with C).
data BorC = ItsB B | ItsC C

step4 :: BorC -> D
step4 x = case x of { ItsB b -> D; ItsC c -> D }

-- step1    step2
--    \       /
--   ItsB   ItsC
--     \   /
--     step4

questionAnswers(1)

yourAnswerToTheQuestion