txt: ## dist_zef-masukomi-Function-Validation.md
  [![Actions Status](https://github.com/masukomi/Function-Validation/actions/workflows/test.yml/badge.svg)](https://github.com/masukomi/Function-Validation/actions)
  
  # NAME
  
  Function::Validation - Functions to help you validate the signature of functions
  
  Think of it as a quasi-type system for functional programming.
  
  # SYNOPSIS
  
  ```
  use Function::Validation;
  
  #validate a specific function
  my sub func(Int $x, Int $y, Bool :$translate, :$rotate) {};
  validate-function(&func, (Int, Int, Bool, Any), Mu); # => True
  #                        ^--inputs              ^--return
  
  # generate a reusable validator
  my $validator = generate-func-validator((Int, Int, Bool, Any), Mu);
  $validator(&func); # => True
  
  my $lambda = sub (){"noparams"};
  validate-function($lambda, [], Str);  # => True
  validate-function($lambda, [], Mu);   # => True
  validate-function($lambda, [], Any);  # => False (Any isn't a catch-all like Mu)
  
  my $lamda_validator = generate-func-validator([], Mu);
  $lambda_validator($lambda);           # => True
  
  my $function_with_where = sub (Int $x where $x < 10) {$x}
  validate-function($function_with_where, [Int], Mu); # => True
  
  # extract the argument types from a function
  my @types = function-arg-types(&func); #=> [(Int) (Int) (Bool) (Any)]
  
  ```
  
  ## DESCRIPTION
  
  Function::Validation validates a function you've been passed to ensure it takes the inputs you expect and provides the output you expect.
  
  Useful in functional programming when you don't have any Classes and thus can't use a `role` or class type to enforce valid input types.
  
  ## BUT...
  
  How does
  
  ```
  validate-function(&func, (Int, Int, Bool, Any), Mu)
  
  ```
  
  differ from
  
  ```
  &func.signature ~~ :(Int,Int,Bool :$translate,Any :$rotate --> Mu)
  
  ```
  
  ?
  
  * The former is more self evident to readers.
  * The former doesn't require developers to have knowledge of the `.signature` function which new devs are unlikely to have.
  
  How does
  
  ```
  function-arg-types(&func)
  
  ```
  
  differ from
  
  ```
  &func.signature.params».type
  
  ```
  
  ?
  
  * The former makes what's happening more self-evident to readers.
  * The former doesn't require developers to have knowledge of the `.signature` and `.params` functions, or why you can't call `.params` on the function directly.
  
  How does is distinguish between
  
  ```
  sub foo(Str :$thing)
  
  ```
  
  and
  
  ```
  sub bar(Str :$other)
  
  ```
  
  ? They can't be called the same way.
  
  **It doesn't!** If you know how to teach it to do this, please [make a Pull Request](https://github.com/masukomi/Function-Validation/pulls), with unit tests.
  
  ### AUTHOR
  
  [masukomi](https://masukomi.org)
  
  # COPYRIGHT AND LICENSE
  
  Copyright 2022
  
  This library is free software; you can redistribute it and/or modify it under the MIT license
  
  ### sub validate-function
  
  ```
  sub validate-function(
      Sub $function,
      Positional $arg_types,
      Mu $return_type = Mu
  ) returns Bool
  
  ```
  
  a function to validate the signature of other functions
  
  ## class Mu $
  
  a reference to the function you want to test
  
  ## class Mu $
  
  A list of the types. If unspecified use Mu
  
  ## class Mu $
  
  The expected return type of the function.
  
  ### sub generate-func-validator
  
  ```
  sub generate-func-validator(
      Positional $arg_types,
      Mu $return_type = Mu
  ) returns Sub
  
  ```
  
  A function to generate a validator to validate the signature of functions
  
  ## class Mu $
  
  A list of the types. If unspecified use Mu
  
  ## class Mu $
  
  The expected return type of the function.
  
  ### sub function-arg-types
  
  ```
  sub function-arg-types(
      Sub $function
  ) returns Seq
  
  ```
  
  a function to extract the types of the arguments of a function
  
  ## class Mu $
  
  the function you want to know the argument types of
  