{"id":13415210,"url":"https://github.com/leandromoh/Curryfy","last_synced_at":"2025-03-14T22:33:02.584Z","repository":{"id":52446730,"uuid":"106121282","full_name":"leandromoh/Curryfy","owner":"leandromoh","description":"Provides strongly typed extensions methods for C# delegates to take advantages of functional programming techniques, like currying and partial application.","archived":false,"fork":false,"pushed_at":"2023-08-13T18:14:02.000Z","size":162,"stargazers_count":69,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-04T15:45:59.263Z","etag":null,"topics":["csharp","curry","currying","delegates","dotnet","dotnet-core","fsharp","partial-application","partial-functions","uncurry"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leandromoh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["leandromoh"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2017-10-07T18:33:18.000Z","updated_at":"2024-10-03T15:35:10.000Z","dependencies_parsed_at":"2024-01-05T20:51:33.876Z","dependency_job_id":"7383fdfc-04a5-4e56-9f63-2d8cca760821","html_url":"https://github.com/leandromoh/Curryfy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoh%2FCurryfy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoh%2FCurryfy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoh%2FCurryfy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoh%2FCurryfy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leandromoh","download_url":"https://codeload.github.com/leandromoh/Curryfy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221514000,"owners_count":16835757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","curry","currying","delegates","dotnet","dotnet-core","fsharp","partial-application","partial-functions","uncurry"],"created_at":"2024-07-30T21:00:45.093Z","updated_at":"2025-03-14T22:33:02.565Z","avatar_url":"https://github.com/leandromoh.png","language":"C#","funding_links":["https://github.com/sponsors/leandromoh"],"categories":["Functional programming","C#"],"sub_categories":[],"readme":"[![Fuget](https://www.fuget.org/packages/Curryfy/badge.svg)](https://www.fuget.org/packages/Curryfy)\n[![Nuget](https://img.shields.io/nuget/v/curryfy?style=flat-square)](https://www.nuget.org/packages/curryfy)\n[![Nuget](https://img.shields.io/nuget/dt/curryfy?style=flat-square)](https://www.nuget.org/packages/curryfy)\n\n# Curryfy\n\nProvides strongly typed extensions methods for C# delegates to take advantages of functional programming techniques, like currying and partial application.  \nConcepts very well known in functional languages like Haskell, F#, Scala, etc.\n\n## What and Why?\n\nCurryfy offers strongly typed extensions that lets you take some benefits of functional programming:\n\n* easy reuse of more abstract functions. \n* create new functions out of an existing function by fixing some parameters\n* convenient way to partially apply a function\n\n## Features\n\n* Extension methods for Currying and UnCurrying\n* Extension methods for Partial Application, with 3 possible approaches\n* Robust and strongly typed\n* Self contained with no dependencies\n* Easily installed through NuGet\n* Supports **.NET 3.5+** and **.NET Core** (.NET Standard 2.0+)\n\n## Installation\n\nSimply reference Curryfy.dll and you are good to go!\n\nCurryfy is also available via NuGet:\n\n```\nPM\u003e Install-Package Curryfy  \n```\n\nOr visit: [https://www.nuget.org/packages/Curryfy](https://www.nuget.org/packages/Curryfy)\n\n## Using the library\n\nAll helper methods are available as extension methods under the `Curryfy` namespace.  \nThey are divided into 7 static classes to avoid method signature ambiguities:\n\n- `CurryExtensions` class  \nProvides methods for curry and uncurry on `Func` delegates.\n\n- `PartialIncrementalActionExtensions` and `PartialIncrementalFuncExtensions` classes  \nProvides methods for partial application on `Func` and `Action` delegates, respecting parameters order.  \nYou can pass only the first argument, only the first and second, only the first, second and third, and so on.  \nSo for a delegate with `N` parameters, there are `N-1` overloads available.  \nThe `-1` overload not avaible is the one with all parameters, which is the delegate itself.  \n\n- `PartialSubsetActionExtensions` and `PartialSubsetFuncExtensions` classes  \nProvides methods for partial application on delegates, without respecting parameters order.  \nYou can pass arguments arbitrarily, regardless of its positions.  \nSo for a delegate with `N` parameters, there are `(2^N)-2` (2 to the power of N, minus 2) overloads available (see [powerset](https://en.wikipedia.org/wiki/Power_set)).  \nThe `-2` overloads not avaible are the one with no parameters and the one with all parameters, which is the delegate itself.  \n\n- `PartialDiscardActionExtensions` and `PartialDiscardFuncExtensions` classes  \nProvides methods for partial application on delegates, without respecting parameters order.  \nIt is similar to `PartialSubset` classes, however in the method call these one rely on arguments  \nposition rather than their names. Which can be more convenient in some situations.  \n\n## Core concepts\n\nConsider the code snippet below as part of all examples:\n\n```csharp\nFunc\u003cint, int, int, int\u003e add = (a, b, c) =\u003e a + b + c;\n```\n\n### [Partial Application](https://en.wikipedia.org/wiki/Partial_application)\n\nPartial application is the process of pass part of the arguments of a function, returning a function that receives the rest of the arguments.\nIf you provide 1 out of 3 arguments, it'll return a function that takes 2 arguments.\nIf you provide 2 out of 3 arguments, it'll return a function that takes 1 argument. \n\nThis feature is available for delegates [Func](https://msdn.microsoft.com/pt-br/library/bb549151(v=vs.110).aspx) and [Action](https://msdn.microsoft.com/pt-br/library/018hxwa8(v=vs.110).aspx) through `ApplyPartial` extension method.\n\nThis method has 1232 overloads.\n\n```csharp\nusing static Curryfy.PartialIncrementalFuncExtensions;\n\nvar add12 = add.ApplyPartial(5, 7); // add12 is Func\u003cint, int\u003e\nvar add5 = add.ApplyPartial(5);     // add5 is Func\u003cint, int, int\u003e\nvar x = add12(3) + add5(7, 3);      // 15 + 15\n```\n\nNote that using the incremental approach, we can only pass the third argument after pass the first and second.  \nThis approach is used by languages like Haskell and F#.  \nHowever using the subset approach, we can pass arguments arbitrarily.  \nYou can pass the only first and the third arguments of a function with 5 parameters, for example.  \n\n```csharp\nusing static Curryfy.PartialSubsetFuncExtensions;\n\nvar add3 = add.ApplyPartial(arg3: 3);   // parameter c receives 3\nvar add10 = add3.ApplyPartial(arg2: 7); // parameter b receives 7\nvar x = add10(5);                       // parameter a receives 5\nConsole.WriteLine(x);                   // x = 15\n```\n\nUsing the discard approach, we can rely on arguments position instead of name.  \nThis approach is used by languages like Scala.  \nThe previous example using discard approach:  \n\n```csharp\nusing static Curryfy.PartialDiscardFuncExtensions;\nusing static Curryfy.Discard;\n\nvar add3 = add.ApplyPartial(_, _, 3);   // parameter c receives 3\nvar add10 = add3.ApplyPartial(_, 7);    // parameter b receives 7\nvar x = add10(5);                       // parameter a receives 5\nConsole.WriteLine(x);                   // x = 15\n```\n\nNote: when using [C# discard feature](https://docs.microsoft.com/dotnet/csharp/discards) in the same scope that discard approach, \nyou should use double underscore (`__`) instead of single underscore (`_`) in the method call. That is, instead of `sum(_, 3)` is `sum(__, 3)`.  \nIf not using in same scope single underscore is fine.\n\nWhich one of these 3 approaches fits better depending of situation. For example, if you have a function with 4 parameters and want to pass only the third, \nmight be more interesting to specify the desired argument `f(arg3: \"foo\")` rather than use discard `f(_, _, \"foo\", _)`. \nIn general:\n\n* If you want to pass arguments respecting order, incremental approach is better.  \n* If you want to pass arguments arbitrarily and skip most arguments, subset approach tends to fit better.  \n* If you want to pass arguments arbitrarily and pass most arguments, discard approach tends to fit better.  \n\nIf you want, it is possible to enable more than one approach at the same time, for example:\n\n```c#\nusing static Curryfy.PartialIncrementalFuncExtensions;\nusing static Curryfy.PartialDiscardFuncExtensions;\nusing static Curryfy.Discard;\n\nFunc\u003cstring, char, int, bool\u003e f = (s, c, i) =\u003e s[i] == c;\n\nvar g = f.ApplyPartial(_, 'b', 1); // using discard approach, g is Func\u003cstring, bool\u003e\n\nvar h = f.ApplyPartial(\"ab\", 'b'); // using incremental approach, h is Func\u003cint, bool\u003e\n``` \n\n### [Currying](https://en.wikipedia.org/wiki/Currying)\n\nCurrying is the process of splitting a function with multiple arguments into a nested chain of one argument functions.\nTherefore a curried function is a function which takes its arguments one at a time, returning a new function at each step.\n\nThis feature is available for [Func](https://msdn.microsoft.com/pt-br/library/bb549151(v=vs.110).aspx) delegates through `Curry` extension method.\n\nThis method has 15 overloads.\n\n```csharp\nusing static Curryfy.CurryExtensions;\n\nvar addCurried = add.Curry();   // addCurried is Func\u003cint, Func\u003cint, Func\u003cint, int\u003e\u003e\u003e\n\nvar add5 = addCurried(5);       // add5 is Func\u003cint, Func\u003cint, int\u003e\u003e\nvar add12 = add5(7);            // add12 is Func\u003cint, int\u003e\nvar x = add12(3);               // x is 15\n\nvar y = addCurried(5)(7)(3);    // y is 15\n```\n\n### [UnCurrying](https://en.wikipedia.org/wiki/Currying)\n\nUnCurrying is the process of transforms a curried function in a function which takes all of its arguments at once.\n\nThis feature is available for [Func](https://msdn.microsoft.com/pt-br/library/bb549151(v=vs.110).aspx) delegates through `UnCurry` extension method.\n\nThis method has 15 overloads.\n\n```csharp\nusing static Curryfy.CurryExtensions;\n\nvar curried = add.Curry();            // curried is Func\u003cint, Func\u003cint, Func\u003cint, int\u003e\u003e\u003e\nvar add5 = curried(5);                // add5 is Func\u003cint, Func\u003cint, int\u003e\u003e\nvar uncurried = add5.UnCurry();       // uncurried is Func\u003cint, int, int\u003e\n\nvar x = uncurried(7, 3) + curried(5)(7)(3);    // 15 + 15\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandromoh%2FCurryfy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleandromoh%2FCurryfy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandromoh%2FCurryfy/lists"}