% Function Composition Function Composition -------------------- \begin{code} module Composition where \end{code} A Plus Function --------------- Consider a simple `plus` function \begin{code} {-@ plus :: x:Int -> y:Int -> {v:Int | v = x + y} @-} plus :: Int -> Int -> Int plus x y = x + y \end{code} A Simple Addition ----------------- Consider a simple use of `plus` a function that adds `3` to its input: \begin{code} {-@ plus3' :: x:Int -> {v:Int | v = x + 3} @-} plus3' :: Int -> Int plus3' x = x + 3 \end{code} - The refinement type captures its behaviour... - ... and LiquidHaskell easily verifies this type. A Composed Variant ------------------ Instead, suppose we defined the previous function by composition We first add `2` to the argument and then add `1` to the intermediate result... \begin{code} {-@ plus3'' :: x:Int -> {v:Int | v = x + 3} @-} plus3'' :: Int -> Int plus3'' = (plus 1) . (plus 2) \end{code} but verification **fails** as we need a way to **compose** the refinements! **Problem** What is a suitable description of the compose operator \begin{code} _ (.) :: (b -> c) -> (a -> b) -> (a -> c) \end{code} that lets us **relate** `a` and `c` via `b` ? Composing Refinements, Abstractly --------------------------------- - We can analyze the *composition* operator - With a very *descriptive* abstract refinement type! \begin{code} {-@ cc :: forall < p :: b -> c -> Prop , q :: a -> b -> Prop>. f:(x:b -> c

) -> g:(x:a -> b) -> y:a -> exists[z:b].c

@-} cc :: (b -> c) -> (a -> b) -> a -> c cc f g x = f (g x) \end{code} Using Composition ----------------- We can verify the desired `plus3` function: \begin{code} {-@ plus3 :: x:Int -> {v:Int | v = x + 3} @-} plus3 :: Int -> Int plus3 = (+ 1) `cc` (+ 2) \end{code} LiquidHaskell verifies the above, by **instantiating** - `p` with `v = x + 1` - `q` with `v = x + 2` which lets it infer that the output of `plus3` has type: - `exists [z:{v=y+2}]. {v = z + 1}` which is a subtype of `{v:Int | v = 3}`