PackageTrack
Sign in Get early access

fpdart

Functional programming in Dart and Flutter. All the main functional programming types and patterns fully documented, tested, and with examples.

1.2.0 265K downloads/mo #739 most downloaded on pub.dev SandroMaglione/fpdart

What this package is like to depend on

Last release 9 months ago

29 Oct 2025

Release timing varies

gaps range from 1 weeks to 12 months

Nearly every release is documented

notes for 25 of 26 stable releases

Nothing withdrawn

no release was ever pulled

5 years old

31 releases · first in 2021

1 release in the last 12 months

see the full history below

Release timeline

31 releases · May 2021 to Oct 2025
2022 2023 2024 2025 2026
Release Pre-release

Releases

latest 31
  1. 2.0.0-dev.3 03 Apr 2024 pre-release

    Nothing published for this version

  2. 2.0.0-dev.2 28 Mar 2024 pre-release

    Nothing published for this version

  3. 2.0.0-dev.1 23 Mar 2024 pre-release

    Nothing published for this version

  4. 1.2.0 29 Oct 2025
    Release notes
    • Added toTaskOptionFlat, toTaskEitherFlat, fromTaskFlatten to TaskOption and TaskEither
    • Added new iterable extension functions singleOption, elementAtOption, singleWhereOption, lastWhereOption
    • Minor internal improvements
    • Status update for fpdart v2 (full discussion here)
    Open source →
  5. 1.1.1 07 Nov 2024
    Release notes
    • Fixed broken documentation links
    Open source →
    Release notes
    • Fixed broken documentation links
    Open source →
  6. 1.1.0 13 Aug 2023
    Release notes
    • Improved performance of some iterable based functions in Iterable and Map extension (thanks to @lrhn 🎉)

    • Added lookupEq and dropRight on Iterable extension

    [].lookupEq(Eq.eqInt, 5) // None()
    [1, 2, 3, 4].lookupEq(Eq.eqInt, 5) // None()
    [1, 2, 3, 4].lookupEq(Eq.eqInt, 3) // Some(3)
    [1, 6, 4, 3, 2].lookupEq(Eq.by((n) => n % 3, Eq.eqInt), 0) // Some(6)
    
    [1, 2].dropRight(3) // []
    [1, 2, 3, 4].dropRight(1) // [1, 2, 3]
    • Added lookupKeyEq on Map extension
    <String, int>{'a': 1, 'b': 2, 'c': 3, 'd': 4}.lookupKeyEq(Eq.eqString, 'b'); // Some('b')
    <String, int>{'a': 1, 'b': 2, 'c': 3, 'd': 4}.lookupKeyEq(Eq.eqString, 'e'); // None()
    Open source →
    Release notes
    • Improved performance of some iterable based functions in Iterable and Map extension (thanks to lrhn 🎉)

    • Added lookupEq and dropRight on Iterable extension

    [].lookupEq(Eq.eqInt, 5) // None()
    [1, 2, 3, 4].lookupEq(Eq.eqInt, 5) // None()
    [1, 2, 3, 4].lookupEq(Eq.eqInt, 3) // Some(3)
    [1, 6, 4, 3, 2].lookupEq(Eq.by((n) => n % 3, Eq.eqInt), 0) // Some(6)
    
    [1, 2].dropRight(3) // []
    [1, 2, 3, 4].dropRight(1) // [1, 2, 3]
    
    • Added lookupKeyEq on Map extension
    <String, int>{'a': 1, 'b': 2, 'c': 3, 'd': 4}.lookupKeyEq(Eq.eqString, 'b'); // Some('b')
    <String, int>{'a': 1, 'b': 2, 'c': 3, 'd': 4}.lookupKeyEq(Eq.eqString, 'e'); // None()
    
    Open source →
  7. 1.0.0 26 Jul 2023
    Release notes
    • Minimum environment dart sdk to 3.0.0 ⚠️ (Dart 3️⃣)
    environment:
      sdk: ">=3.0.0 <4.0.0"
    • Added new ReaderTaskEither type
      • ReaderTaskEither models a complete program using Reader for dependency injection, Task to perform asynchronous computation, and Either to handle errors 🎯
    • Added new ReaderTask type
    • Either as sealed class (Dart 3️⃣)
      • You can now use exhaustive pattern matching (Left or Right)
    /// Pattern matching
    final match = right.match(
      (l) => print('Left($l)'),
      (r) => print('Right($r)'),
    );
    
    /// or use Dart's pattern matching as well 🤝
    final dartMatch = switch (right) {
      Left(value: final l) => 'Left($l)',
      Right(value: final r) => 'Right($r)',
    };
    • Option as sealed class (Dart 3️⃣)
      • You can now use exhaustive pattern matching (None or Some)
    /// Pattern matching
    final match = option.match(
      () => print('None'),
      (a) => print('Some($a)'),
    );
    
    /// or use Dart's pattern matching as well 🤝
    final dartMatch = switch (option) {
      None() => 'None',
      Some(value: final a) => 'Some($a)',
    };
    • Types marked as final (no extends nor implements) (Dart 3️⃣)
      • Unit
      • Reader
      • State
      • StateAsync
      • IO
      • IORef
      • IOOption
      • IOEither
      • Task
      • TaskOption
      • TaskEither
      • ReaderTask
      • ReaderTaskEither
    • Removed Tuple2, use Dart 3 Records instead (Tuple2(a, b) becomes simply (a, b) 🎯) ⚠️ (Dart 3️⃣)
      • Updated all internal APIs to use records instead of Tuple2
    • Major refactoring of Iterable and List extension methods
      • Improved performance
      • Correct return types (Iterable and List) (#65)
      • Added the following methods
        • prependAll (Iterable)
        • intersperse (Iterable)
        • difference (Iterable)
        • filterWithIndex (Iterable)
      • Fixed the following methods ⚠️
        • takeWhileRight: Resulting List now in reversed order as expected
        • dropWhileRight: Resulting List now in reversed order as expected
      • Updated the following methods ⚠️
        • foldRight, foldRightWithIndex (List): Changed parameter order in combine function
        • zipWith (Iterable): Changed parameters definition, no more curried
      • Renamed the following methods ⚠️
        • plusconcat (Iterable)
        • concatflatten (on Iterable<Iterable<T>>)
      • Removed the following methods ⚠️
        • concatMap (use flatMap instead)
        • bind (use flatMap instead)
        • bindWithIndex (use flatMapWithIndex instead)
        • concatMapWithIndex (use flatMapWithIndex instead)
    • Refactoring of Map extension methods
      • Improved performance
      • Added the following methods
        • lookupEq
        • lookupWithKeyEq
      • Removed the following methods ⚠️
        • member (use containsKey instead)
        • elem (use containsValue instead)
        • toIterable (use toSortedList instead)
      • Updated the following methods ⚠️
        • toIterable renamed to toSortedList (return a List instead of Iterable)
        • modifyAt changed parameter order and no more curried
        • modifyAtIfPresent changed parameter order and no more curried
        • updateAt no more curried
        • updateAtIfPresent no more curried
        • deleteAt no more curried
        • upsertAt no more curried
        • pop no more curried
        • foldLeft no more curried
        • foldLeftWithKey no more curried
        • foldLeftWithIndex no more curried
        • foldLeftWithKeyAndIndex no more curried
        • foldRight no more curried
        • foldRightWithKey no more curried
        • foldRightWithIndex no more curried
        • foldRightWithKeyAndIndex no more curried
        • union no more curried
        • intersection no more curried
        • isSubmap no more curried
        • collect no more curried
        • difference no more curried
    • Added conversions helpers from String to num, int, double, and bool using Option and Either (both as extension methods on String and as functions) (#80)
      • toNumOption
      • toIntOption
      • toDoubleOption
      • toBoolOption
      • toNumEither
      • toIntEither
      • toDoubleEither
      • toBoolEither
    /// As extension on [String]
    final result = "10".toNumOption; /// `Some(10)`
    final result = "10.5".toNumOption; /// `Some(10.5)`
    final result = "0xFF".toIntOption; /// `Some(255)`
    final result = "10.5".toDoubleOption; /// `Some(10.5)`
    final result = "NO".toBoolEither(() => "left"); /// `Left("left")`
    
    /// As functions
    final result = toNumOption("10"); /// `Some(10)`
    final result = toNumOption("10.5"); /// `Some(10.5)`
    final result = toIntOption("0xFF"); /// `Some(255)`
    final result = toDoubleOption("10.5"); /// `Some(10.5)`
    final result = toBoolEither("NO", () => "left"); /// `Left("left")`
    • Changed dateNow, now, random, and randomBool to getter functions
    /// Before
    Option<T> getRandomOption<T>(T value) => randomBool()
        .map((isValid) => isValid ? some(value) : none<T>())
        .run();
    
    /// Now
    Option<T> getRandomOption<T>(T value) => randomBool
        .map((isValid) => isValid ? some(value) : none<T>())
        .run();
    • Removed Predicate class and added extension methods in its place ⚠️
    bool isEven(int n) => n % 2 == 0;
    bool isDivisibleBy3(int n) => n % 3 == 0;
    
    final isOdd = isEven.negate;
    final isEvenAndDivisibleBy3 = isEven.and(isDivisibleBy3);
    final isEvenOrDivisibleBy3 = isEven.or(isDivisibleBy3);
    final isStringWithEvenLength = isEven.contramap<String>((n) => n.length);
    • Updated curry / uncarry extensions ⚠️
      • Renamed curry to curryAll for functions with 3, 4, 5 parameters
      • Changed definition of curry to curry only the first parameter
      • Changed uncurry and curry extension to getter function
      • Removed curry and uncurry as functions (use extension method instead)
      • Added curryLast (curry last parameter)
    int Function(int) subtractCurried(int n1) => (n2) => n1 - n2;
    
    /// Before
    subtractCurried.uncurry()(10, 5);
    
    final addFunction = (int a, int b) => a + b;
    final add = curry2(addFunction);
    
    [1, 2, 3].map(add(1));  // returns [2, 3, 4]
    
    /// New
    subtractCurried.uncurry(10, 5);
    
    final addFunction = (int a, int b) => a + b;
    final add = addFunction.curry;
    
    [1, 2, 3].map(add(1)); // returns [2, 3, 4]
    [1, 2, 3].map(addFunction.curry(1)); // returns [2, 3, 4]
    • Changed Eq static constructors to methods
      • or
      • and
    • Added xor method to Eq
    • Moved DateTime instances of Eq as Eq static members
    /// Before
    final eq = dateEqYear; // Global
    
    /// Now
    final eq = Eq.dateEqYear;
    • Added Eq instances for num, int, double, String, and bool
    [1, 2, 3].difference(Eq.eqInt, [2, 3, 4]); /// `[1]`
    • Added new method to Eq
      • contramap
    class Parent {
      final int value1;
      final double value2;
      const Parent(this.value1, this.value2);
    }
    
    /// Equality for values of type [Parent] based on their `value1` ([int]).
    final eqParentInt = Eq.eqInt.contramap<Parent>(
      (p) => p.value1,
    );
    
    /// Equality for of type [Parent] based on their `value2` ([double]).
    final eqParentDouble = Eq.eqDouble.contramap<Parent>(
      (p) => p.value2,
    );
    • Changed reverse in Order from static constructor to getter method
    /// Before
    final reversed = Order.reverse(instance);
    
    /// Now
    final reversed = instance.reverse;
    • Moved DateTime instances of Order as Order static members
    • Added Order instances for num, int, double
    • Added new methods to Order
      • between
      • clamp
      • contramap
    class Parent {
      final int value1;
      final double value2;
      const Parent(this.value1, this.value2);
    }
    
    /// Order values of type [Parent] based on their `value1` ([int]).
    final orderParentInt = Order.orderInt.contramap<Parent>(
      (p) => p.value1,
    );
    
    /// Order values of type [Parent] based on their `value2` ([double]).
    final orderParentDouble = Order.orderDouble.contramap<Parent>(
      (p) => p.value2,
    );
    • Removed bool extension (match and fold), use the ternary operator or pattern matching instead ⚠️
    final boolValue = Random().nextBool();
    
    /// Before
    final result = boolValue.match<int>(() => -1, () => 1);
    final result = boolValue.fold<int>(() => -1, () => 1);
    
    /// Now
    final result = boolValue ? 1 : -1;
    final result = switch (boolValue) { true => 1, false => -1 };
    Open source →
    Release notes
    • Minimum environment dart sdk to 3.0.0 ⚠️ (Dart 3️⃣)
    environment:
      sdk: ">=3.0.0 <4.0.0"
    
    • Added new ReaderTaskEither type
      • ReaderTaskEither models a complete program using Reader for dependency injection, Task to perform asynchronous computation, and Either to handle errors 🎯
    • Added new ReaderTask type
    • Either as sealed class (Dart 3️⃣)
      • You can now use exhaustive pattern matching (Left or Right)
    /// Pattern matching
    final match = right.match(
      (l) => print('Left($l)'),
      (r) => print('Right($r)'),
    );
    
    /// or use Dart's pattern matching as well 🤝
    final dartMatch = switch (right) {
      Left(value: final l) => 'Left($l)',
      Right(value: final r) => 'Right($r)',
    };
    
    • Option as sealed class (Dart 3️⃣)
      • You can now use exhaustive pattern matching (None or Some)
    /// Pattern matching
    final match = option.match(
      () => print('None'),
      (a) => print('Some($a)'),
    );
    
    /// or use Dart's pattern matching as well 🤝
    final dartMatch = switch (option) {
      None() => 'None',
      Some(value: final a) => 'Some($a)',
    };
    
    • Types marked as final (no extends nor implements) (Dart 3️⃣)
      • Unit
      • Reader
      • State
      • StateAsync
      • IO
      • IORef
      • IOOption
      • IOEither
      • Task
      • TaskOption
      • TaskEither
      • ReaderTask
      • ReaderTaskEither
    • Removed Tuple2, use Dart 3 Records instead (Tuple2(a, b) becomes simply (a, b) 🎯) ⚠️ (Dart 3️⃣)
      • Updated all internal APIs to use records instead of Tuple2
    • Major refactoring of Iterable and List extension methods
      • Improved performance
      • Correct return types (Iterable and List) (#65)
      • Added the following methods
        • prependAll (Iterable)
        • intersperse (Iterable)
        • difference (Iterable)
        • filterWithIndex (Iterable)
      • Fixed the following methods ⚠️
        • takeWhileRight: Resulting List now in reversed order as expected
        • dropWhileRight: Resulting List now in reversed order as expected
      • Updated the following methods ⚠️
        • foldRight, foldRightWithIndex (List): Changed parameter order in combine function
        • zipWith (Iterable): Changed parameters definition, no more curried
      • Renamed the following methods ⚠️
        • plusconcat (Iterable)
        • concatflatten (on Iterable<Iterable<T>>)
      • Removed the following methods ⚠️
        • concatMap (use flatMap instead)
        • bind (use flatMap instead)
        • bindWithIndex (use flatMapWithIndex instead)
        • concatMapWithIndex (use flatMapWithIndex instead)
    • Refactoring of Map extension methods
      • Improved performance
      • Added the following methods
        • lookupEq
        • lookupWithKeyEq
      • Removed the following methods ⚠️
        • member (use containsKey instead)
        • elem (use containsValue instead)
        • toIterable (use toSortedList instead)
      • Updated the following methods ⚠️
        • toIterable renamed to toSortedList (return a List instead of Iterable)
        • modifyAt changed parameter order and no more curried
        • modifyAtIfPresent changed parameter order and no more curried
        • updateAt no more curried
        • updateAtIfPresent no more curried
        • deleteAt no more curried
        • upsertAt no more curried
        • pop no more curried
        • foldLeft no more curried
        • foldLeftWithKey no more curried
        • foldLeftWithIndex no more curried
        • foldLeftWithKeyAndIndex no more curried
        • foldRight no more curried
        • foldRightWithKey no more curried
        • foldRightWithIndex no more curried
        • foldRightWithKeyAndIndex no more curried
        • union no more curried
        • intersection no more curried
        • isSubmap no more curried
        • collect no more curried
        • difference no more curried
    • Added conversions helpers from String to num, int, double, and bool using Option and Either (both as extension methods on String and as functions) (#80)
      • toNumOption
      • toIntOption
      • toDoubleOption
      • toBoolOption
      • toNumEither
      • toIntEither
      • toDoubleEither
      • toBoolEither
    /// As extension on [String]
    final result = "10".toNumOption; /// `Some(10)`
    final result = "10.5".toNumOption; /// `Some(10.5)`
    final result = "0xFF".toIntOption; /// `Some(255)`
    final result = "10.5".toDoubleOption; /// `Some(10.5)`
    final result = "NO".toBoolEither(() => "left"); /// `Left("left")`
    
    /// As functions
    final result = toNumOption("10"); /// `Some(10)`
    final result = toNumOption("10.5"); /// `Some(10.5)`
    final result = toIntOption("0xFF"); /// `Some(255)`
    final result = toDoubleOption("10.5"); /// `Some(10.5)`
    final result = toBoolEither("NO", () => "left"); /// `Left("left")`
    
    • Changed dateNow, now, random, and randomBool to getter functions
    /// Before
    Option<T> getRandomOption<T>(T value) => randomBool()
        .map((isValid) => isValid ? some(value) : none<T>())
        .run();
    
    /// Now
    Option<T> getRandomOption<T>(T value) => randomBool
        .map((isValid) => isValid ? some(value) : none<T>())
        .run();
    
    • Removed Predicate class and added extension methods in its place ⚠️
    bool isEven(int n) => n % 2 == 0;
    bool isDivisibleBy3(int n) => n % 3 == 0;
    
    final isOdd = isEven.negate;
    final isEvenAndDivisibleBy3 = isEven.and(isDivisibleBy3);
    final isEvenOrDivisibleBy3 = isEven.or(isDivisibleBy3);
    final isStringWithEvenLength = isEven.contramap<String>((n) => n.length);
    
    • Updated curry / uncarry extensions ⚠️
      • Renamed curry to curryAll for functions with 3, 4, 5 parameters
      • Changed definition of curry to curry only the first parameter
      • Changed uncurry and curry extension to getter function
      • Removed curry and uncurry as functions (use extension method instead)
      • Added curryLast (curry last parameter)
    int Function(int) subtractCurried(int n1) => (n2) => n1 - n2;
    
    /// Before
    subtractCurried.uncurry()(10, 5);
    
    final addFunction = (int a, int b) => a + b;
    final add = curry2(addFunction);
    
    [1, 2, 3].map(add(1));  // returns [2, 3, 4]
    
    /// New
    subtractCurried.uncurry(10, 5);
    
    final addFunction = (int a, int b) => a + b;
    final add = addFunction.curry;
    
    [1, 2, 3].map(add(1)); // returns [2, 3, 4]
    [1, 2, 3].map(addFunction.curry(1)); // returns [2, 3, 4]
    
    • Changed Eq static constructors to methods
      • or
      • and
    • Added xor method to Eq
    • Moved DateTime instances of Eq as Eq static members
    /// Before
    final eq = dateEqYear; // Global
    
    /// Now
    final eq = Eq.dateEqYear;
    
    • Added Eq instances for num, int, double, String, and bool
    [1, 2, 3].difference(Eq.eqInt, [2, 3, 4]); /// `[1]`
    
    • Added new method to Eq
      • contramap
    class Parent {
      final int value1;
      final double value2;
      const Parent(this.value1, this.value2);
    }
    
    /// Equality for values of type [Parent] based on their `value1` ([int]).
    final eqParentInt = Eq.eqInt.contramap<Parent>(
      (p) => p.value1,
    );
    
    /// Equality for of type [Parent] based on their `value2` ([double]).
    final eqParentDouble = Eq.eqDouble.contramap<Parent>(
      (p) => p.value2,
    );
    
    • Changed reverse in Order from static constructor to getter method
    /// Before
    final reversed = Order.reverse(instance);
    
    /// Now
    final reversed = instance.reverse;
    
    • Moved DateTime instances of Order as Order static members
    • Added Order instances for num, int, double
    • Added new methods to Order
      • between
      • clamp
      • contramap
    class Parent {
      final int value1;
      final double value2;
      const Parent(this.value1, this.value2);
    }
    
    /// Order values of type [Parent] based on their `value1` ([int]).
    final orderParentInt = Order.orderInt.contramap<Parent>(
      (p) => p.value1,
    );
    
    /// Order values of type [Parent] based on their `value2` ([double]).
    final orderParentDouble = Order.orderDouble.contramap<Parent>(
      (p) => p.value2,
    );
    
    • Removed bool extension (match and fold), use the ternary operator or pattern matching instead ⚠️
    final boolValue = Random().nextBool();
    
    /// Before
    final result = boolValue.match<int>(() => -1, () => 1);
    final result = boolValue.fold<int>(() => -1, () => 1);
    
    /// Now
    final result = boolValue ? 1 : -1;
    final result = switch (boolValue) { true => 1, false => -1 };
    

    Open source →
  8. 1.0.0-beta.1 27 May 2023 pre-release

    Nothing published for this version

  9. 0.6.0 06 May 2023
    Release notes
    • Do notation #97 (Special thanks to @tim-smart 🎉)
      • All the main types now have a Do() constructor used to initialize a Do notation chain
      • Updated examples to use Do notation (new recommended API 🎯)
    /// Without the Do notation
    String goShopping() => goToShoppingCenter()
        .alt(goToLocalMarket)
        .flatMap(
          (market) => market.buyBanana().flatMap(
                (banana) => market.buyApple().flatMap(
                      (apple) => market.buyPear().flatMap(
                            (pear) => Option.of('Shopping: $banana, $apple, $pear'),
                          ),
                    ),
              ),
        )
        .getOrElse(
          () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷‍♂️',
        );
    /// Using the Do notation
    String goShoppingDo() => Option.Do(
          ($) {
            final market = $(goToShoppingCenter().alt(goToLocalMarket));
            final amount = $(market.buyAmount());
    
            final banana = $(market.buyBanana());
            final apple = $(market.buyApple());
            final pear = $(market.buyPear());
    
            return 'Shopping: $banana, $apple, $pear';
          },
        ).getOrElse(
          () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷‍♂️',
        );
    • Added new IOOption type
    • Added conversion methods from and to all classes (IO, IOOption, IOEither, Task, TaskOption, TaskEither)
      • Removed toTask in IOEither (use toTaskEither instead) ⚠️
    • Improved performance of fpdart's sortBy list extension #101 (thanks to @hbock-42 🎉)
    • Updated pokeapi_functional example to Riverpod v2 #99 (thanks to @utamori 🎉)
    • Updated repository folder structure #105
    Open source →
    Release notes
    • Do notation #97 (Special thanks to @tim-smart 🎉)
      • All the main types now have a Do() constructor used to initialize a Do notation chain
      • Updated examples to use Do notation (new recommended API 🎯)
    /// Without the Do notation
    String goShopping() => goToShoppingCenter()
        .alt(goToLocalMarket)
        .flatMap(
          (market) => market.buyBanana().flatMap(
                (banana) => market.buyApple().flatMap(
                      (apple) => market.buyPear().flatMap(
                            (pear) => Option.of('Shopping: $banana, $apple, $pear'),
                          ),
                    ),
              ),
        )
        .getOrElse(
          () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷‍♂️',
        );
    
    /// Using the Do notation
    String goShoppingDo() => Option.Do(
          (_) {
            final market = _(goToShoppingCenter().alt(goToLocalMarket));
            final amount = _(market.buyAmount());
    
            final banana = _(market.buyBanana());
            final apple = _(market.buyApple());
            final pear = _(market.buyPear());
    
            return 'Shopping: $banana, $apple, $pear';
          },
        ).getOrElse(
          () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷‍♂️',
        );
    
    • Added new IOOption type
    • Added conversion methods from and to all classes (IO, IOOption, IOEither, Task, TaskOption, TaskEither)
      • Removed toTask in IOEither (use toTaskEither instead) ⚠️
    • Improved performance of fpdart's sortBy list extension #101 (thanks to @hbock-42 🎉)
    • Updated pokeapi_functional example to Riverpod v2 #99 (thanks to @utamori 🎉)
    • Updated repository folder structure #105
    Open source →
  10. 0.6.0-dev.1 08 Mar 2023 pre-release

    Nothing published for this version

  11. 0.5.0 04 Mar 2023
    Release notes
    • Updates to Option type #92 [⚠️ BREAKING CHANGE]
      • Added const factory constructor for None (fixes #95)
      • Removed Alt and Foldable type classes, the following methods are not available anymore
        • foldLeft
        • foldRight
        • foldMap
        • foldRightWithIndex
        • foldLeftWithIndex
        • length
        • any
        • all
        • concatenate
        • plus
        • prepend
        • append
    • Updated examples and fixed lint warnings #93 (thanks to tim-smart 🎉)
    Open source →
    Release notes
    • Updates to Option type #92 [⚠️ BREAKING CHANGE]
      • Added const factory constructor for None (fixes #95)
      • Removed Alt and Foldable type classes, the following methods are not available anymore
        • foldLeft
        • foldRight
        • foldMap
        • foldRightWithIndex
        • foldLeftWithIndex
        • length
        • any
        • all
        • concatenate
        • plus
        • prepend
        • append
    • Updated examples and fixed lint warnings #93 (thanks to tim-smart 🎉)
    Open source →
  12. 0.4.1 25 Feb 2023
    Release notes
    • New methods for Option type (thanks to tim-smart 🎉)
      • flatMapNullable
      • flatMapThrowable
    final option = Option.of(10);
    
    option.flatMapNullable((a) => a + 1); /// 👈 `Some(11)`
    option.flatMapThrowable((a) => a + 1); /// 👈 `Some(11)`
    
    option.flatMapNullable<int>((a) => null); /// 👈 `None()`
    option.flatMapThrowable<int>((a) => throw "fail"); /// 👈 `None()`
    • Improved support fromJson for Option type (thanks [again] to tim-smart 🎉)
      • Allow for decoding of non-primitive types (with custom fromJson constructors)
    /// `fromJson` on `DateTime` with `Option` type
    final now = DateTime.now();
    Option<DateTime>.fromJson(now.toIso8601String(), (a) => DateTime.parse(a as String)); /// 👈 `Some(now)`
    
    Option<DateTime>.fromJson("fail", (a) => DateTime.parse(a as String)); /// 👈 `None()`
    • New extension methods for Map (thanks [once again] to tim-smart 🎉)
      • extract
      • extractMap
    final map = <String, dynamic>{'a': 1, 'b': 2, 'c': 3, 'd': 4};
    map.extract<int>('b'); /// 👈 `Some(2)`
    map.extract<String>('b'); /// 👈 `None()`, not of type `String` ⚠️
    
    final map = <String, dynamic>{'a': 1};
    map.extractMap('a'); /// 👈 `None()`, not a `Map`
    
    final map = <String, dynamic>{'a': {'b': 2} };
    map.extractMap('a'); /// 👈 `Some({'b': 2})`
    • Option.of and Option.none factories const (thanks to f-person 🎉)

    Note: People who have the prefer_const_constructors lint enabled will notice a warning to use const 🤝

    Open source →
    Release notes
    • New methods for Option type (thanks to tim-smart 🎉)
      • flatMapNullable
      • flatMapThrowable
    final option = Option.of(10);
    
    option.flatMapNullable((a) => a + 1); /// 👈 `Some(11)`
    option.flatMapThrowable((a) => a + 1); /// 👈 `Some(11)`
    
    option.flatMapNullable<int>((a) => null); /// 👈 `None()`
    option.flatMapThrowable<int>((a) => throw "fail"); /// 👈 `None()`
    
    • Improved support fromJson for Option type (thanks [again] to tim-smart 🎉)
      • Allow for decoding of non-primitive types (with custom fromJson constructors)
    /// `fromJson` on `DateTime` with `Option` type
    final now = DateTime.now();
    Option<DateTime>.fromJson(now.toIso8601String(), (a) => DateTime.parse(a as String)); /// 👈 `Some(now)`
    
    Option<DateTime>.fromJson("fail", (a) => DateTime.parse(a as String)); /// 👈 `None()`
    
    • New extension methods for Map (thanks [once again] to tim-smart 🎉)
      • extract
      • extractMap
    final map = <String, dynamic>{'a': 1, 'b': 2, 'c': 3, 'd': 4};
    map.extract<int>('b'); /// 👈 `Some(2)`
    map.extract<String>('b'); /// 👈 `None()`, not of type `String` ⚠️
    
    final map = <String, dynamic>{'a': 1};
    map.extractMap('a'); /// 👈 `None()`, not a `Map`
    
    final map = <String, dynamic>{'a': {'b': 2} };
    map.extractMap('a'); /// 👈 `Some({'b': 2})`
    
    • Option.of and Option.none factories const (thanks to f-person 🎉)

    Note: People who have the prefer_const_constructors lint enabled will notice a warning to use const 🤝

    Open source →
  13. 0.4.0 16 Dec 2022
    Release notes
    • Added extension methods to work with nullable types (T?)
      • From T? to fpdart's types
        • toOption
        • toEither
        • toTaskOption
        • toIOEither
        • toTaskEither
        • toTaskEitherAsync
        • fromNullable (Either, IOEither, TaskOption TaskEither)
        • fromNullableAsync (TaskEither)
      • From fpdart's types to T?
        • toNullable (Either)
    /// [Option] <-> `int?`
    int? value1 = 10.toOption().map((t) => t + 10).toNullable();
    
    bool? value2 = value1?.isEven;
    
    /// `bool?` -> [Either] -> `int?`
    int? value3 = value2
        .toEither(() => "Error")
        .flatMap((a) => a ? right<String, int>(10) : left<String, int>("None"))
        .toNullable();
    
    /// `int?` -> [Option]
    Option<int> value4 = (value3?.abs().round()).toOption().flatMap(Option.of);
    • Added toIOEither to Either
    • Removed parameter from Either fromNullable [⚠️ BREAKING CHANGE]
    final either = Either<String, int>.fromNullable(value, (r) => 'none');
    
    /// 👆 Removed the value `(r)` (it was always null anyway 💁🏼‍♂️) 👇
    
    final either = Either<String, int>.fromNullable(value, () => 'none');
    • Added chainEither to TaskEither
    • Added safeCast (Either and Option)
    • Added safeCastStrict (Either and Option)
    int intValue = 10;
    
    /// Unhandled exception: type 'int' is not a subtype of type 'List<int>' in type cast
    final waitWhat = intValue as List<int>;
    final first = waitWhat.first;
    
    /// Safe 🎯
    final wellYeah = Either<String, List<int>>.safeCast(
      intValue,
      (dynamic value) => 'Not a List!',
    );
    final firstEither = wellYeah.map((list) => list.first);
    Open source →
    Release notes
    • Added extension methods to work with nullable types (T?)
      • From T? to fpdart's types
        • toOption
        • toEither
        • toTaskOption
        • toIOEither
        • toTaskEither
        • toTaskEitherAsync
        • fromNullable (Either, IOEither, TaskOption TaskEither)
        • fromNullableAsync (TaskEither)
      • From fpdart's types to T?
        • toNullable (Either)
    /// [Option] <-> `int?`
    int? value1 = 10.toOption().map((t) => t + 10).toNullable();
    
    bool? value2 = value1?.isEven;
    
    /// `bool?` -> [Either] -> `int?`
    int? value3 = value2
        .toEither(() => "Error")
        .flatMap((a) => a ? right<String, int>(10) : left<String, int>("None"))
        .toNullable();
    
    /// `int?` -> [Option]
    Option<int> value4 = (value3?.abs().round()).toOption().flatMap(Option.of);
    
    • Added toIOEither to Either
    • Removed parameter from Either fromNullable [⚠️ BREAKING CHANGE]
    final either = Either<String, int>.fromNullable(value, (r) => 'none');
    
    /// 👆 Removed the value `(r)` (it was always null anyway 💁🏼‍♂️) 👇
    
    final either = Either<String, int>.fromNullable(value, () => 'none');
    
    • Added chainEither to TaskEither
    • Added safeCast (Either and Option)
    • Added safeCastStrict (Either and Option)
    int intValue = 10;
    
    /// Unhandled exception: type 'int' is not a subtype of type 'List<int>' in type cast
    final waitWhat = intValue as List<int>;
    final first = waitWhat.first;
    
    /// Safe 🎯
    final wellYeah = Either<String, List<int>>.safeCast(
      intValue,
      (dynamic value) => 'Not a List!',
    );
    final firstEither = wellYeah.map((list) => list.first);
    
    Open source →
  14. 0.3.0 11 Oct 2022
    Release notes
    • Inverted onSome and onNone functions parameters in match method of Option [⚠️ BREAKING CHANGE] (Read more on why 👉 #56)
    /// Everywhere you are using `Option.match` you must change this:
    final match = option.match(
      (a) => print('Some($a)'),
      () => print('None'), // <- `None` second 👎 
    );
    
    /// to this (invert parameters order):
    final match = option.match(
      () => print('None'), // <- `None` first 👍
      (a) => print('Some($a)'),
    );
    • Added traverse and sequence methods (#55)
      • traverseList
      • traverseListWithIndex
      • sequenceList
      • traverseListSeq
      • traverseListWithIndexSeq
      • sequenceListSeq
    /// "a40" is invalid 💥
    final inputValues = ["10", "20", "30", "a40"];
    
    /// Verify that all the values can be converted to [int] 🔐
    ///
    /// If **any** of them is invalid, then the result is [None] 🙅‍♂️
    final traverseOption = inputValues.traverseOption(
      (a) => Option.tryCatch(
        /// If `a` does not contain a valid integer literal a [FormatException] is thrown
        () => int.parse(a),
      ),
    );
    • Added bindEither method in TaskEither (#58)
    /// Chain [Either] to [TaskEither]
    TaskEither<String, int> binding =
        TaskEither<String, String>.of("String").bindEither(Either.of(20));
    • Added lefts, rights, and partitionEithers methods to Either (#57)
    final list = [
      right<String, int>(1),
      right<String, int>(2),
      left<String, int>('a'),
      left<String, int>('b'),
      right<String, int>(3),
    ];
    final result = Either.partitionEithers(list);
    expect(result.first, ['a', 'b']);
    expect(result.second, [1, 2, 3]);
    • Added bimap method to Either, IOEither, and Tuple2 (#57)
    • Added mapLeft method to IOEither (#57)
    • Added fold method to Option (same as match) (#56)
    • Fixed chainFirst for Either, TaskEither, and IOEither when chaining on a failure (Left) (#47) by DevNico 🎉
    • Added const to all constructors in which it was missing (#59)
    • Minimum environment dart sdk to 2.17.0 ⚠️
    environment:
      sdk: ">=2.17.0 <3.0.0"
    Open source →
    Release notes
    • Inverted onSome and onNone functions parameters in match method of Option [⚠️ BREAKING CHANGE] (Read more on why 👉 #56)
    /// Everywhere you are using `Option.match` you must change this:
    final match = option.match(
      (a) => print('Some($a)'),
      () => print('None'), // <- `None` second 👎 
    );
    
    /// to this (invert parameters order):
    final match = option.match(
      () => print('None'), // <- `None` first 👍
      (a) => print('Some($a)'),
    );
    
    • Added traverse and sequence methods (#55)
      • traverseList
      • traverseListWithIndex
      • sequenceList
      • traverseListSeq
      • traverseListWithIndexSeq
      • sequenceListSeq
    /// "a40" is invalid 💥
    final inputValues = ["10", "20", "30", "a40"];
    
    /// Verify that all the values can be converted to [int] 🔐
    ///
    /// If **any** of them is invalid, then the result is [None] 🙅‍♂️
    final traverseOption = inputValues.traverseOption(
      (a) => Option.tryCatch(
        /// If `a` does not contain a valid integer literal a [FormatException] is thrown
        () => int.parse(a),
      ),
    );
    
    • Added bindEither method in TaskEither (#58)
    /// Chain [Either] to [TaskEither]
    TaskEither<String, int> binding =
        TaskEither<String, String>.of("String").bindEither(Either.of(20));
    
    • Added lefts, rights, and partitionEithers methods to Either (#57)
    final list = [
      right<String, int>(1),
      right<String, int>(2),
      left<String, int>('a'),
      left<String, int>('b'),
      right<String, int>(3),
    ];
    final result = Either.partitionEithers(list);
    expect(result.first, ['a', 'b']);
    expect(result.second, [1, 2, 3]);
    
    • Added bimap method to Either, IOEither, and Tuple2 (#57)
    • Added mapLeft method to IOEither (#57)
    • Added fold method to Option (same as match) (#56)
    • Fixed chainFirst for Either, TaskEither, and IOEither when chaining on a failure (Left) (#47) by DevNico 🎉
    • Added const to all constructors in which it was missing (#59)
    • Minimum environment dart sdk to 2.17.0 ⚠️
    environment:
      sdk: ">=2.17.0 <3.0.0"
    
    Open source →
  15. 0.2.0 16 Jul 2022
    Release notes
    Open source →
    Release notes
    Open source →
  16. 0.1.0 17 Jun 2022
    Release notes
    • Added idFuture and identityFuture methods (#38 by f-person 🎉)
    • Added mapBoth method to Tuple2 (#30)
    • Fixed linting warnings
    • Fixed issue with upsert method for Map (#37) ⚠️
    • Minimum environment dart sdk to 2.16.0 ⚠️
    environment:
      sdk: ">=2.16.0 <3.0.0"
    Open source →
    Release notes
    • Added idFuture and identityFuture methods (#38) by f-person 🎉
    • Added mapBoth method to Tuple2 (#30)
    • Fixed linting warnings
    • Fixed issue with upsert method for Map (#37) ⚠️
    • Minimum environment dart sdk to 2.16.0 ⚠️
    environment:
      sdk: ">=2.16.0 <3.0.0"
    
    Open source →
  17. 0.0.14 31 Jan 2022
    Release notes
    • Updated package linting to lints
    Open source →
  18. 0.0.13 26 Jan 2022
    Release notes
    • New methods to TaskEither, TaskOption, Either, and Option
      • mapLeft (TaskEither)
      • bimap (TaskEither)
      • toTaskEither (Either)
      • toTaskOption (Option)
    • New Blog posts and tutorials section in README
    Open source →
  19. 0.0.12 24 Oct 2021
    Release notes
    • Completed IORef type implementation, documentation, and testing
    Open source →
  20. 0.0.11 22 Sep 2021
    Release notes
    • Fixed major issue in State and StateAsync implementation [BREAKING CHANGE]
      • Methods flatMap, map, map2, map3, ap, andThen, call, and flatten had an implementation issue that has been now fixed
    Open source →
  21. 0.0.10 13 Aug 2021
    Release notes
    • Released introduction to Practical Functional Programming
    • Completed StateAsync type implementation, documentation, and testing
    • Fixed problem with Alt typeclass (#21)
    • Added call method to more easily chain functions in Monad and Monad2
    Open source →
  22. 0.0.9 03 Aug 2021
    Release notes
    Open source →
  23. 0.0.8 13 Jul 2021
    Release notes
    • Released Part 3 of Fpdart, Functional Programming in Dart and Flutter
    • Added Pure Functional Flutter app example (pokeapi_functional)
    • Added flatMapTask and toTask methods to IO to lift and chain IO with Task
    • Added flatMapTask and toTask methods to IOEither to lift and chain IOEither with TaskEither
    • Added pattern matching extension methods to bool (boolean.dart)
    • Added functions to get random int, double, and bool in a functional way (using IO) (random.dart)
    • Added functions, extension methods, Ord, and Eq instances to DateTime (date.dart)
    Open source →
  24. 0.0.7 06 Jul 2021
    Release notes
    • Released Part 2 of Fpdart, Functional Programming in Dart and Flutter
    • Added Compose and Compose2, used to easily compose functions in a chain
    • Added curry and uncurry extensions on functions up to 5 parameters
    • Completed TaskOption type implementation, documentation, and testing
    • Expanded documentation and examples
    • Added TaskEither.tryCatchK and Either.tryCatchK, by tim-smart (#10, #11) 🎉
    Open source →
  25. 0.0.6 29 Jun 2021
    Release notes
    • Released Part 1 of Fpdart, Functional Programming in Dart and Flutter
    • Added functional extension methods on Iterable (List)
    • Completed IOEither type implementation, documentation, and testing
    • Added constF function
    • Added option and optionOf (same as dartz)
    • Added Either.right(r) factory constructor to Either class (same as Either.of(r)) (#3)
    • Added example on reading local file using TaskEither (read_write_file)
    • Added more examples
    • Added constant constructors to Eq and variants, by mateusfccp (#4) 🎉
    Open source →
  26. 0.0.5 20 Jun 2021
    Release notes
    • Completed State type implementation, documentation, and testing
    • Completed Reader type implementation, documentation, and testing
    • Completed IO type implementation, documentation, and testing
    • Merged PR (#2) by jacobaraujo7 🎉
      • Added right and left functions to create instance of Either
      • Added id function (same as identity)
      • Added fold method to Either (same as match)
      • Added bind method to Either (same as flatMap)
      • Added bindFuture method to Either, which returns TaskEither
    Open source →
  27. 0.0.4 15 Jun 2021
    Release notes
    • Completed Unit type documentation
    • Completed Task type implementation, documentation, and testing
    • Completed TaskEither type implementation, documentation, and testing
    • Completed implementation, documentation, and testing of Foldable instance on Option and Either [BREAKING CHANGE]
    • Completed Tuple2 type implementation, documentation, and testing [BREAKING CHANGE]
    • Renamed fold method of Foldable to foldLeft [BREAKING CHANGE]
    • Updated methods API (foldRight, foldLeft, etc.) of Foldable instances (Option, Either, Tuple) [BREAKING CHANGE]
    • IList not longer working correctly (waiting for a better solution for immutable collections) [BREAKING CHANGE]
    Open source →
  28. 0.0.3 13 Jun 2021
    Release notes
    • Changed name of type Maybe to Option to be inline with fp-ts, cats, and dartz [BREAKING CHANGE]
    Open source →
  29. 0.0.2 13 Jun 2021
    Release notes

    First major release:

    Types

    • Either
    • IList
    • Maybe
    • Reader
    • State
    • Task
    • TaskEither
    • Tuple
    • Unit

    Typeclasses

    • Alt
    • Applicative
    • Band
    • BoundedSemilattice
    • CommutativeGroup
    • CommutativeMonoid
    • CommutativeSemigroup
    • Eq
    • Extend
    • Filterable
    • Foldable
    • Functor
    • Group
    • Hash
    • HKT
    • Monad
    • Monoid
    • Order
    • PartialOrder
    • Semigroup
    • Semilattice

    Examples

    • Either
    • curry
    • Maybe
    • Reader
    • State
    Open source →
  30. 0.0.2+1 13 Jun 2021

    Nothing published for this version

  31. 0.0.1 28 May 2021
    Release notes
    • Eq
    • Hash
    • PartialOrder
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive