The DSL perspective
As it is discussed in the comments, the question can be seen as parsing of a particular DSL in WL.
Direct implementation
This notebook screenshot image shows a direct implementation corresponding to the Haskell example in the question with the package "FunctionalParsers.m":

Details on how to use the package "FunctionalParsers.m" can be found here: "Functional parsers for an integration requests language grammar.pdf".
Some notes on the operators used:
Here is the code:
pOptionValue =
ParsePredicate[
StringMatchQ[#,
Except[{"-", "(", ")", "[", "]", WhitespaceCharacter}] ..] &];
pProgramName = Program\[CircleDot]pOptionValue;
pProjectOption =
Project\[CircleDot]((ParseSymbol["-p"]\[CirclePlus]ParseSymbol[
"--project"])\[CircleTimes]pOptionValue);
pSchemeOption =
Scheme\[CircleDot]((ParseSymbol["-s"]\[CirclePlus]ParseSymbol[
"--scheme"])\[CircleTimes]pOptionValue);
pConfigurationOption =
Configuration\[CircleDot]((ParseSymbol[
"-c"]\[CirclePlus]ParseSymbol[
"--configuration"])\[CircleTimes]pOptionValue);
pHelp = Help\[CircleDot](ParseSymbol["-h"]\[CirclePlus]ParseSymbol[
"--help"]);
pOptions =
ParseMany[
pProjectOption\[CirclePlus]pSchemeOption\[CirclePlus]\
pConfigurationOption\[CirclePlus]pHelp];
pCommand =
ParseShortest[
Flatten\[CircleDot](pProgramName\[CircleTimes]ParseOption[pOptions])];
Answer using parser generation from EBNF
I am posting this part of the answer since the following command line DSL was easy to program with "FunctionalParsers.m" (it took me 15-20 minutes) using EBNF specification and parsers generation.
First we program the command line DSL in Extended Backus-Naur Form (EBNF):
Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/FunctionalParsers.m"]
ebnfCommandLine = "
<command-line> = <program> , [ <arg-list> ] ;
<program> = '_WordString' <@ CLProgram ;
<arg-list> = { <arg> } <@ CLArgumentList ;
<arg> = <timeout-spec> | <source-spec> | <help> | <option-name> , <option-value> <@ CLArgument ;
<option-name> = '_String' <@ CLOptionName ;
<option-value> = '_String' <@ CLOptionValue ;
<help> = '--help' | '-h' <@ CLHelp ;
<timeout-spec> = ( '--timeout' | '-t' ) &> '_?NumberQ' <@ CLTimeoutSpec ;
<source-spec> = ( '--source' | '-src' ) &> '_String' <@ CLSourceSpec ;
";
Note that in the EBNF string above I have used function wrappers for the parsing rules. Some of them can be skipped (e.g. CLArgumentList
).
The following generates the parsers from the EBNF string:
GenerateParsersFromEBNF[ToTokens[ebnfCommandLine]];
LeafCount[res]
(* 258 *)
Here we overwrite the parser for <option-name>
in order to make it more specific. (Hard to do in the EBNF string.)
pOPTIONNAME =
ParseApply[CLOptionName,
ParsePredicate[
StringMatchQ[#, ("-" | "--") ~~ (WordCharacter ..)] &]];
Here is a table of example command parsings:
commands = {"example",
"example --help",
"example1 --timeout 123",
"example2 -t 34 -src ./MyFile.php",
"exampleUknownOption --timeout 34 --source ./MyFile.php -out ./MyFile.PHP",
"exampleFail1 --timeout 34 --source ./MyFile.php -;out ./MyFile.PHP",
"exampleFail2 5 6 out xxx",
"exampleMisSpell --timeout 34 --sourse ./MyFile.php"
};
ParsingTestTable[ParseShortest[pCOMMANDLINE], commands, "Layout" -> "Vertical"]

For more details on programming DSLs see the blog post:
"Creating and programming domain specific languages".
wolframscript
, or parsing of a particular DSL in WL. $\endgroup$