diff --git a/FunctionalProgramming.md b/FunctionalProgramming.md index e64bbd1..e484e9a 100644 --- a/FunctionalProgramming.md +++ b/FunctionalProgramming.md @@ -1,12 +1,44 @@ # Functional programming -| Language/Paradigm | Higher-order functions | Currying | Pure functions | Tail recursion | -| ----------------- | ---------------------- | ----------------------- | -------------- | -------------- | -| JavaScript | X | via anonymous functions | | | -| Python | X | via anonymous functions | | | -| Typescript | X | via anonymous functions | | | -| Java | X | via anonymous functions | | | -| C# | X | via anonymous functions | | | -| C++ | X | via anonymous functions | | X | -| PHP | X | via anonymous functions | | | -| Go | X | via anonymous functions | | | +## higher-order functions + +| Language/Paradigm | Higher-order functions | Currying | +| ----------------- | ---------------------- | ----------------------- | +| JavaScript | ✅ | via anonymous functions | +| Python | ✅ | via anonymous functions | +| Typescript | ✅ | via anonymous functions | +| Java | ✅ | via anonymous functions | +| C# | ✅ | via anonymous functions | +| C++ | ✅ | via anonymous functions | +| PHP | ✅ | via anonymous functions | +| Go | ✅ | via anonymous functions | + +## Pure functions + +None of these languages support Pure functions + + +## Recursion +| Language/Paradigm | Tail recursion | folds | unfolds | +| ----------------- | -------------- | ------------------------------------------ | ------- | +| JavaScript | ❌ | .reduce() method on arrays | ❌ | +| Python | ❌ | functools.reduce() function on iterables | ❌ | +| Typescript | ❌ | .reduce() method on arrays | ❌ | +| Java | ❌ | .reduce() method on streamable collections | ❌ | +| C# | ❌ | .Aggregate() method on collections | ❌ | +| C++ | ✅ | std::accumulate on sequences. | ❌ | +| PHP | ❌ | array_reduce() on array | ❌ | +| Go | ❌ | ❌ | ❌ | + + +## Type systems +| Language/Paradigm | Product types | sum types | Pattern Matching | +| ----------------- | ------------- | ------------------------------ | --------------------------------- | +| JavaScript | | ❌ | ❌ | +| Python | | ✅since 3.5 with typing.Union | ✅since 3.10 with match statement | +| Typescript | | ✅discriminated unions | switch-case with shared field. | +| Java | | Simulated via Sealed Interface | since Java 21 | +| C# | | Simulated via Sealed Class | since C# 9.0 | +| C++ | | since C++17 with std::variant | since C++17 with std::visit | +| PHP | | ❌ | ❌ | +| Go | | ❌ | ❌ | diff --git a/c++/Typing discipline/SumTypes/main.cpp b/c++/Typing discipline/SumTypes/main.cpp new file mode 100644 index 0000000..3063b60 --- /dev/null +++ b/c++/Typing discipline/SumTypes/main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +class Empty {}; + +class Node; + +using LinkedList = std::variant, Empty>; + +class Node { +public: + int value; + LinkedList next; + + Node(int val, LinkedList nxt) : value(val), next(nxt) {} +}; + +void processList(const LinkedList& list) { + std::visit([](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v>) { + std::cout << "Node with value: " << arg->value << std::endl; + processList(arg->next); + } else { + std::cout << "End of list" << std::endl; + } + }, list); +} + +int main() { + LinkedList myList = std::make_shared(1, std::make_shared(2, std::make_shared(3, Empty()))); + processList(myList); + return 0; +} diff --git a/c-sharp/Functional Programming/SumTypes/Main.cs b/c-sharp/Functional Programming/SumTypes/Main.cs new file mode 100644 index 0000000..4e5149a --- /dev/null +++ b/c-sharp/Functional Programming/SumTypes/Main.cs @@ -0,0 +1,24 @@ +public abstract record LinkedList(); + +public sealed record Node(int Value, LinkedList Next) : LinkedList; + +public sealed record Empty() : LinkedList; + +public class Program { + public static void ProcessList(LinkedList list) { + switch (list) { + case Node node: + Console.WriteLine($"Node with value: {node.Value}"); + ProcessList(node.Next); + break; + case Empty: + Console.WriteLine("End of list"); + break; + } + } + + public static void Main() { + LinkedList myList = new Node(1, new Node(2, new Node(3, new Empty()))); + ProcessList(myList); + } +} diff --git a/java/Functional Programming/SumTypes/Main.java b/java/Functional Programming/SumTypes/Main.java new file mode 100644 index 0000000..ec08db7 --- /dev/null +++ b/java/Functional Programming/SumTypes/Main.java @@ -0,0 +1,22 @@ +public sealed interface LinkedList permits Node, Empty {} + +public record Node(int value, LinkedList next) implements LinkedList {} + +public final class Empty implements LinkedList {} + +public class Main { + public static void processList(LinkedList list) { + switch (list) { + case Node node -> { + System.out.println("Node with value: " + node.value()); + processList(node.next()); + } + case Empty empty -> System.out.println("End of list"); + } + } + + public static void main(String[] args) { + LinkedList myList = new Node(1, new Node(2, new Node(3, new Empty()))); + processList(myList); + } +} diff --git a/python/Functional Programming/SumTypes.py b/python/Functional Programming/SumTypes.py new file mode 100644 index 0000000..2ebb302 --- /dev/null +++ b/python/Functional Programming/SumTypes.py @@ -0,0 +1,24 @@ +from dataclasses import dataclass + +@dataclass +class Node: + value: int + next: 'LinkedList' + +@dataclass +class Empty: + pass + +# Using the union operator to define the LinkedList type +LinkedList = Node | Empty + +def process_list(lst: LinkedList): + match lst: + case Node(value, next): + print(f"Node with value: {value}") + process_list(next) + case Empty(): + print("End of list") + +my_list = Node(1, Node(2, Node(3, Empty()))) +process_list(my_list) diff --git a/typescript/Functional Programming/Currying.ts b/typescript/Functional Programming/Currying.ts index e6e3b3e..60dbf96 100644 --- a/typescript/Functional Programming/Currying.ts +++ b/typescript/Functional Programming/Currying.ts @@ -1,4 +1,5 @@ -function add(a: number): (number) => number { +(() => { + function add(a: number): (number) => number { return function(b: number): number { return a + b; }; @@ -6,3 +7,4 @@ function add(a: number): (number) => number { const addFive = add(5); console.log(addFive(3)); // 8 +})() \ No newline at end of file diff --git a/typescript/Functional Programming/SumTypes.ts b/typescript/Functional Programming/SumTypes.ts new file mode 100644 index 0000000..ae5acac --- /dev/null +++ b/typescript/Functional Programming/SumTypes.ts @@ -0,0 +1,29 @@ +(() => { + type LinkedList = Node | Empty; + + class Node { + kind: "Node" = "Node"; + constructor(public value: number, public next: LinkedList) {} + } + + class Empty { + kind: "Empty" = "Empty"; + } + + function processList(list: LinkedList): void { + switch (list.kind) { + case "Node": + console.log(`Node with value: ${list.value}`); + processList(list.next); + break; + case "Empty": + console.log("End of list"); + break; + } + } + + // Example usage + const myList: LinkedList = new Node(1, new Node(2, new Node(3, new Empty()))); + processList(myList); + +})()