Typowy wykres dekompozycyjny w Haskell

Załóżmy, że tworzę potok danych, który będzie przetwarzał pliki tekstowe. Mam następujące typy i funkcje:

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

Dla każdego kroku funkcji {1..3} poniżej chciałbym móc utworzyć nowy plik z istniejącego pliku, robiąc coś takiego:

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

Następnie chcę być w stanie ułożyć je w wykres (aby funkcje mogły mieć wiele wejść), aby osiągnąć następujące cele:

Mogę przechodzić przez strukturę danych, aby stwierdzić, które funkcje zapewniają dane wejściowe, do których inni

Struktura danych będzie wpisywać sprawdzanie w czasie kompilacji, tak aby każdy nieprawidłowy układ rzucał błąd typu.

Wiem, jak zrobić 1 bez 2 (daj im wspólną klasę) i wiem, jak zrobić 2 bez 1 (po prostu użyj (.)), Ale nie wiem, jak to zrobić jednocześnie. Jakieś pomysły? TIA.

Aktualizacja

Odpowiedź AndrewC jest na miejscu i zapewnia mi większą część drogi, ponieważ mogę następnie zbudować wykres metadanych (nazw) przy użyciu mapy i sprawdzić go osobno w tym samym czasie, jednak potrzebuję także elastycznego polimorfizmu. Poniższy przykład rozwiązuje ten problem, ale z dwoma poważnymi zastrzeżeniami:

Nie jestem zmuszony być wyczerpującym w dopasowywaniu wzorców w kroku 4.To nudne; mogą istnieć dziesiątki typów polimorficznych w stylu „BorC”, które nie robią nic poza umożliwieniem polimorfizmu, a nawet bardzo bezpiecznie (patrz 1). Próbowałem dopasować dopasowanie do członków klasy typu (Step4Input z przykładamiB iC) ale to nie zadziałało (powiedziałCouldn'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