
import Control.Applicative


andThenReader :: (env -> a) -> (a -> env -> b) -> (env -> b)
andThenReader f g = \env -> g (f env) env


applyWithMax f n max
  | f n > max = Nothing
  | otherwise = Just $ f n

squareWithMax = applyWithMax (^2)

foo :: (Int,Int,Int) -> Int -> Maybe Int
foo (n1,n2,n3) max =
  squareWithMax n1 max
    <|> squareWithMax n2 max
    <|> squareWithMax n3 max

foo' :: (Int,Int,Int) -> Int -> Maybe Int
foo' (n1,n2,n3) = do
  mn1 <- squareWithMax n1
  mn2 <- squareWithMax n2
  mn3 <- squareWithMax n3
  pure $ mn1 <|> mn2 <|> mn3

foo'' :: (Int,Int,Int) -> Int -> Maybe Int
foo'' (n1,n2,n3) =
  pure (\mn1 mn2 mn3 -> mn1 <|> mn2 <|> mn3)
    <*> squareWithMax n1
    <*> squareWithMax n2
    <*> squareWithMax n3
