import VarArgs -- | Example of using sequenceArgs. -- -- Note how the entire function is produced by a monad action, -- and then we unwrap the args from the function out of the monad, -- leaving us with a monadic function that returns the result after -- all the arguments have been applied. sequenceArgsExample :: IO (Int -> Bool -> IO String) -> (Int -> Bool -> IO String) sequenceArgsExample = sequenceArgs @'[Int, Bool] @String mapResultExample :: forall a. Read a => (Int -> Bool -> String) -> (Int -> Bool -> a) mapResultExample = mapResult @'[Int, Bool] @String @a read -- Example of using foldlArgs. -- -- foldlArgs doesn't take a function and produce a result, unlike sequenceArgs and mapResult. -- Instead, it only cares about the type list of arguments, and it synthesizes a function that -- folds over the arguments, producing a result of the given type. -- -- This necessarily requires a type class constraint on the arguments, since we need a type -- class to actually let us do anything with the arguments. foldlArgsExample :: Int -> Bool -> [String] foldlArgsExample = foldlArgs @'[Int, Bool] @Show @[String] (\xs x -> xs ++ [show x]) [] -- | Nearly the same as the foldlArgs example, but specifically uses a monoid -- since that's a common need. foldMapArgsExample :: Int -> Bool -> [String] foldMapArgsExample = foldMapArgs @'[Int, Bool] @Show @[String] (pure . show) hoistResultExample :: (Int -> Bool -> Maybe String) -> (Int -> Bool -> Either String String) hoistResultExample = hoistResult @'[Int, Bool] @String @Maybe @(Either String) (maybe (Left "Nothing") Right) -- | Print each argument and return the count of how many arguments were printed. -- -- Usage: foldMArgsExample @'[Int, Bool] 12 False foldMArgsExample :: forall args. (VarArgs args, AllArgs Show args) => args :->: IO Int foldMArgsExample = foldMArgs @args @Show @Int @IO (\count x -> print x >> pure (count + 1)) 0 main :: IO () main = putStrLn "If things compiled, then the library is working."