# Managing error types in function composition

Using function composition to compose translations and other compiler passes makes it really clear what passes are involved. Such compositions are a great way to write code, especially in the UFT driver, but it’s not always easy to get them to type check. This short note presents some heuristics that make it easier.

The heuristics include a trick: I redefine ! to be a synonym for Error.map. I can then write >>> !, which looks sort of like an infix operator, even though it isn’t really. With that trick, I can compose two functions $$f$$ and $$g$$ based on what type comes out of each function. (I assume that no error type ever goes directly into either function.)

• If neither function returns an error type, compose them with >>>.

• If both $$f$$ and $$g$$ return error types, compose them with >=>.

• If $$f$$ returns an error type but $$g$$ does not, compose them with >>> !.

• If $$f$$ returns ’b error list, for any 'b, use >>> to compose $$f$$ with Error.list. In this situation, no other $$g$$ is useful. But the composition $$f$$ >>> Error.list can then be composed with a function $$g'$$ that expects an input of type 'b list.

Here’s a table of types:

Function compositions
$$f$$’s type operator $$g$$’s type (or $$g$$) composition’s type
'a -> 'b >>> 'b -> 'c 'a -> 'c
'a -> 'b error >>> ! 'b -> 'c 'a -> 'c error
'a -> 'b error >=> 'b -> 'c error 'a -> 'c error
'a -> 'b error list >>> Error.list 'a -> 'b list error

And here’s an algebraic law:

f >=> (g >>> h) ===  f >>> ! g >=> h

I recommend using this law from left to right, so it can be used to un-nest pipelines.