diff --git a/analysis_options.yaml b/analysis_options.yaml index 3952c558..4701dcd9 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -11,5 +11,4 @@ analyzer: strict-raw-types: true errors: annotate_overrides: error - mixin_inherits_from_not_object: ignore deprecated_field: ignore diff --git a/example/json_serializable/pubspec.lock b/example/json_serializable/pubspec.lock index fb36576a..754419a1 100644 --- a/example/json_serializable/pubspec.lock +++ b/example/json_serializable/pubspec.lock @@ -175,7 +175,7 @@ packages: path: "../.." relative: true source: path - version: "0.0.14" + version: "0.1.1" frontend_server_client: dependency: transitive description: diff --git a/example/pokeapi_functional/pubspec.lock b/example/pokeapi_functional/pubspec.lock index 552a35a0..19394d89 100644 --- a/example/pokeapi_functional/pubspec.lock +++ b/example/pokeapi_functional/pubspec.lock @@ -28,7 +28,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -98,7 +98,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" charcode: dependency: transitive description: @@ -126,7 +126,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" code_builder: dependency: transitive description: @@ -168,7 +168,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" file: dependency: transitive description: @@ -213,7 +213,7 @@ packages: path: "../.." relative: true source: path - version: "0.0.14" + version: "0.1.1" freezed: dependency: "direct main" description: @@ -318,14 +318,14 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" mime: dependency: transitive description: @@ -346,7 +346,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" pedantic: dependency: transitive description: @@ -414,7 +414,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -449,14 +449,14 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: diff --git a/example/read_write_file/pubspec.lock b/example/read_write_file/pubspec.lock index 5f0642ae..6eb3083f 100644 --- a/example/read_write_file/pubspec.lock +++ b/example/read_write_file/pubspec.lock @@ -7,7 +7,7 @@ packages: path: "../.." relative: true source: path - version: "0.0.13" + version: "0.1.1" lint: dependency: "direct dev" description: @@ -16,4 +16,4 @@ packages: source: hosted version: "1.5.3" sdks: - dart: ">=2.13.0 <3.0.0" + dart: ">=2.16.0 <3.0.0" diff --git a/lib/src/either.dart b/lib/src/either.dart index 17972964..8b997d31 100644 --- a/lib/src/either.dart +++ b/lib/src/either.dart @@ -25,6 +25,8 @@ abstract class _EitherHKT {} /// an instance of [Left] containing information about the kind of error that occurred. abstract class Either extends HKT2<_EitherHKT, L, R> with + Functor2<_EitherHKT, L, R>, + Applicative2<_EitherHKT, L, R>, Monad2<_EitherHKT, L, R>, Foldable2<_EitherHKT, L, R>, Alt2<_EitherHKT, L, R>, diff --git a/lib/src/io.dart b/lib/src/io.dart index 318008fa..c4179d85 100644 --- a/lib/src/io.dart +++ b/lib/src/io.dart @@ -7,7 +7,8 @@ abstract class _IOHKT {} /// can **cause side effects**, yields a value of type `A` and **never fails**. /// /// If you want to represent a synchronous computation that may fail, see [IOEither]. -class IO extends HKT<_IOHKT, A> with Monad<_IOHKT, A> { +class IO extends HKT<_IOHKT, A> + with Functor<_IOHKT, A>, Applicative<_IOHKT, A>, Monad<_IOHKT, A> { final A Function() _run; /// Build an instance of [IO] from `A Function()`. diff --git a/lib/src/io_either.dart b/lib/src/io_either.dart index 2b3c91cc..3a7741d0 100644 --- a/lib/src/io_either.dart +++ b/lib/src/io_either.dart @@ -4,6 +4,8 @@ import 'io.dart'; import 'option.dart'; import 'task_either.dart'; import 'typeclass/alt.dart'; +import 'typeclass/applicative.dart'; +import 'typeclass/functor.dart'; import 'typeclass/hkt.dart'; import 'typeclass/monad.dart'; @@ -16,7 +18,11 @@ abstract class _IOEitherHKT {} /// /// If you want to represent a synchronous computation that may never fail, see [IO]. class IOEither extends HKT2<_IOEitherHKT, L, R> - with Monad2<_IOEitherHKT, L, R>, Alt2<_IOEitherHKT, L, R> { + with + Functor2<_IOEitherHKT, L, R>, + Applicative2<_IOEitherHKT, L, R>, + Monad2<_IOEitherHKT, L, R>, + Alt2<_IOEitherHKT, L, R> { final Either Function() _run; /// Build an instance of [IOEither] from `Either Function()`. diff --git a/lib/src/option.dart b/lib/src/option.dart index 43053b12..3881c0b9 100644 --- a/lib/src/option.dart +++ b/lib/src/option.dart @@ -3,10 +3,12 @@ import 'function.dart'; import 'task_option.dart'; import 'tuple.dart'; import 'typeclass/alt.dart'; +import 'typeclass/applicative.dart'; import 'typeclass/eq.dart'; import 'typeclass/extend.dart'; import 'typeclass/filterable.dart'; import 'typeclass/foldable.dart'; +import 'typeclass/functor.dart'; import 'typeclass/hkt.dart'; import 'typeclass/monad.dart'; import 'typeclass/monoid.dart'; @@ -63,6 +65,8 @@ abstract class _OptionHKT {} /// ``` abstract class Option extends HKT<_OptionHKT, T> with + Functor<_OptionHKT, T>, + Applicative<_OptionHKT, T>, Monad<_OptionHKT, T>, Foldable<_OptionHKT, T>, Alt<_OptionHKT, T>, diff --git a/lib/src/reader.dart b/lib/src/reader.dart index 7f625d84..7b8b4abb 100644 --- a/lib/src/reader.dart +++ b/lib/src/reader.dart @@ -6,7 +6,11 @@ abstract class ReaderHKT {} /// `Reader` allows to read values `A` from a dependency/context `R` /// without explicitly passing the dependency between multiple nested /// function calls. -class Reader extends HKT2 with Monad2 { +class Reader extends HKT2 + with + Functor2, + Applicative2, + Monad2 { final A Function(R r) _read; /// Build a [Reader] given `A Function(R)`. diff --git a/lib/src/state.dart b/lib/src/state.dart index 73217d27..af4f984d 100644 --- a/lib/src/state.dart +++ b/lib/src/state.dart @@ -12,7 +12,11 @@ abstract class _StateHKT {} /// `S` is a State (e.g. the current _State_ of your Bank Account). /// `A` is value that you _extract out of the [State]_ /// (Account Balance fetched from the current state of your Bank Account `S`). -class State extends HKT2<_StateHKT, S, A> with Monad2<_StateHKT, S, A> { +class State extends HKT2<_StateHKT, S, A> + with + Functor2<_StateHKT, S, A>, + Applicative2<_StateHKT, S, A>, + Monad2<_StateHKT, S, A> { final Tuple2 Function(S state) _run; /// Build a new [State] given a `Tuple2 Function(S)`. diff --git a/lib/src/state_async.dart b/lib/src/state_async.dart index 479d038e..38213572 100644 --- a/lib/src/state_async.dart +++ b/lib/src/state_async.dart @@ -15,7 +15,10 @@ abstract class _StateAsyncHKT {} /// /// Used when fetching and updating the state is **asynchronous**. Use [State] otherwise. class StateAsync extends HKT2<_StateAsyncHKT, S, A> - with Monad2<_StateAsyncHKT, S, A> { + with + Functor2<_StateAsyncHKT, S, A>, + Applicative2<_StateAsyncHKT, S, A>, + Monad2<_StateAsyncHKT, S, A> { final Future> Function(S state) _run; /// Build a new [StateAsync] given a `Future> Function(S)`. diff --git a/lib/src/task.dart b/lib/src/task.dart index 1412f95f..56f670c0 100644 --- a/lib/src/task.dart +++ b/lib/src/task.dart @@ -6,14 +6,15 @@ abstract class _TaskHKT {} /// [Task] represents an asynchronous computation that yields a value of type `A` and **never fails**. /// /// If you want to represent an asynchronous computation that may fail, see [TaskEither]. -class Task extends HKT<_TaskHKT, A> with Monad<_TaskHKT, A> { +class Task extends HKT<_TaskHKT, A> + with Functor<_TaskHKT, A>, Applicative<_TaskHKT, A>, Monad<_TaskHKT, A> { final Future Function() _run; /// Build a [Task] from a function returning a [Future]. const Task(this._run); /// Build a [Task] that returns `a`. - factory Task.of(A a) => Task(() async => a); + factory Task.of(A a) => Task(() async => a); /// Flat a [Task] contained inside another [Task] to be a single [Task]. factory Task.flatten(Task> task) => task.flatMap(identity); diff --git a/lib/src/task_either.dart b/lib/src/task_either.dart index 5117be46..4ea103ef 100644 --- a/lib/src/task_either.dart +++ b/lib/src/task_either.dart @@ -3,6 +3,8 @@ import 'function.dart'; import 'option.dart'; import 'task.dart'; import 'typeclass/alt.dart'; +import 'typeclass/applicative.dart'; +import 'typeclass/functor.dart'; import 'typeclass/hkt.dart'; import 'typeclass/monad.dart'; @@ -14,7 +16,11 @@ abstract class _TaskEitherHKT {} /// /// If you want to represent an asynchronous computation that never fails, see [Task]. class TaskEither extends HKT2<_TaskEitherHKT, L, R> - with Monad2<_TaskEitherHKT, L, R>, Alt2<_TaskEitherHKT, L, R> { + with + Functor2<_TaskEitherHKT, L, R>, + Applicative2<_TaskEitherHKT, L, R>, + Monad2<_TaskEitherHKT, L, R>, + Alt2<_TaskEitherHKT, L, R> { final Future> Function() _run; /// Build a [TaskEither] from a function returning a `Future>`. diff --git a/lib/src/task_option.dart b/lib/src/task_option.dart index afa812ce..cc584145 100644 --- a/lib/src/task_option.dart +++ b/lib/src/task_option.dart @@ -3,6 +3,8 @@ import 'function.dart'; import 'option.dart'; import 'task.dart'; import 'typeclass/alt.dart'; +import 'typeclass/applicative.dart'; +import 'typeclass/functor.dart'; import 'typeclass/hkt.dart'; import 'typeclass/monad.dart'; @@ -17,7 +19,11 @@ abstract class _TaskOptionHKT {} /// If you want to represent an asynchronous computation that returns an object when it fails, /// see [TaskEither]. class TaskOption extends HKT<_TaskOptionHKT, R> - with Monad<_TaskOptionHKT, R>, Alt<_TaskOptionHKT, R> { + with + Functor<_TaskOptionHKT, R>, + Applicative<_TaskOptionHKT, R>, + Monad<_TaskOptionHKT, R>, + Alt<_TaskOptionHKT, R> { final Future> Function() _run; /// Build a [TaskOption] from a function returning a `Future>`. diff --git a/lib/src/typeclass/alt.dart b/lib/src/typeclass/alt.dart index 19d297d0..3c5c6c56 100644 --- a/lib/src/typeclass/alt.dart +++ b/lib/src/typeclass/alt.dart @@ -5,10 +5,10 @@ import 'hkt.dart'; /// /// It provides an `alt` function used to return an alternative value when the /// current one represents a failure (for example, [None] for [Option]). -abstract class Alt extends HKT with Functor { +mixin Alt on HKT, Functor { HKT alt(HKT Function() orElse); } -abstract class Alt2 extends HKT2 with Functor2 { +mixin Alt2 on HKT2, Functor2 { HKT2 alt(HKT2 Function() orElse); } diff --git a/lib/src/typeclass/applicative.dart b/lib/src/typeclass/applicative.dart index b9fa0aed..0b6d0103 100644 --- a/lib/src/typeclass/applicative.dart +++ b/lib/src/typeclass/applicative.dart @@ -1,7 +1,7 @@ import 'functor.dart'; import 'hkt.dart'; -abstract class Applicative extends HKT with Functor { +mixin Applicative on HKT, Functor { HKT pure(B a); HKT ap(HKT a); @@ -9,8 +9,7 @@ abstract class Applicative extends HKT with Functor { HKT map(B Function(A a) f) => ap(pure(f)); } -abstract class Applicative2 extends HKT2 - with Functor2 { +mixin Applicative2 on HKT2, Functor2 { HKT2 pure(C a); HKT2 ap(HKT2 a); diff --git a/lib/src/typeclass/band.dart b/lib/src/typeclass/band.dart index f9c505b4..f4993517 100644 --- a/lib/src/typeclass/band.dart +++ b/lib/src/typeclass/band.dart @@ -3,7 +3,7 @@ import 'package:fpdart/fpdart.dart'; /// Bands are semigroups whose operation /// (i.e. `combine`) is also [**idempotent**](https://en.wikipedia.org/wiki/Idempotence) /// (an operation that can be applied multiple times without changing the result beyond the initial application). -abstract class Band extends Semigroup { +mixin Band on Semigroup { /// Only apply `combine` operation the first time: /// - `n == 1`, then return `a` /// - Otherwise return `combine(a, a)` @@ -21,7 +21,7 @@ abstract class Band extends Semigroup { static Band instance(A Function(A a1, A a2) f) => _Band(f); } -class _Band extends Band { +class _Band with Semigroup, Band { final T Function(T x, T y) comb; _Band(this.comb); diff --git a/lib/src/typeclass/bounded_semilattice.dart b/lib/src/typeclass/bounded_semilattice.dart index c9cf7a89..a72e08e2 100644 --- a/lib/src/typeclass/bounded_semilattice.dart +++ b/lib/src/typeclass/bounded_semilattice.dart @@ -8,8 +8,7 @@ import 'package:fpdart/fpdart.dart'; /// > of the set `{x, y}` exist. /// /// See also [Semilattice] -abstract class BoundedSemilattice extends CommutativeMonoid - with Semilattice { +mixin BoundedSemilattice on CommutativeMonoid, Semilattice { /// Return a `BoundedSemilattice` that reverses the order. @override BoundedSemilattice reverse() => @@ -36,7 +35,15 @@ abstract class BoundedSemilattice extends CommutativeMonoid _BoundedSemilattice(emptyValue, f); } -class _BoundedSemilattice extends BoundedSemilattice { +class _BoundedSemilattice + with + Semigroup, + Monoid, + CommutativeSemigroup, + Band, + Semilattice, + CommutativeMonoid, + BoundedSemilattice { final T emp; final T Function(T x, T y) comb; diff --git a/lib/src/typeclass/commutative_group.dart b/lib/src/typeclass/commutative_group.dart index 696545c5..1075b627 100644 --- a/lib/src/typeclass/commutative_group.dart +++ b/lib/src/typeclass/commutative_group.dart @@ -4,14 +4,21 @@ import 'package:fpdart/fpdart.dart'; /// is a group whose combine operation is [**commutative**](https://en.wikipedia.org/wiki/Commutative_property). /// /// See also [Group] -abstract class CommutativeGroup extends Group with CommutativeMonoid { +mixin CommutativeGroup on Group, CommutativeMonoid { /// Create a `CommutativeGroup` instance from the given function, empty value, and inverse function. static CommutativeGroup instance( A emptyValue, A Function(A a1, A a2) f, A Function(A a) inv) => _CommutativeGroup(emptyValue, f, inv); } -class _CommutativeGroup extends CommutativeGroup { +class _CommutativeGroup + with + Semigroup, + CommutativeSemigroup, + Monoid, + CommutativeMonoid, + Group, + CommutativeGroup { final T Function(T a) inv; final T emp; final T Function(T x, T y) comb; diff --git a/lib/src/typeclass/commutative_monoid.dart b/lib/src/typeclass/commutative_monoid.dart index 8e945e40..56b454ea 100644 --- a/lib/src/typeclass/commutative_monoid.dart +++ b/lib/src/typeclass/commutative_monoid.dart @@ -1,12 +1,12 @@ import 'commutative_semigroup.dart'; import 'monoid.dart'; +import 'semigroup.dart'; /// `CommutativeMonoid` represents a commutative monoid. /// /// A monoid is [**commutative**](https://en.wikipedia.org/wiki/Commutative_property) /// if for all `x` and `y`, `combine(x, y) == combine(y, x)`. -abstract class CommutativeMonoid extends Monoid - with CommutativeSemigroup { +mixin CommutativeMonoid on Monoid, CommutativeSemigroup { /// Return a `CommutativeMonoid` that reverses the order. @override CommutativeMonoid reverse() => @@ -18,7 +18,12 @@ abstract class CommutativeMonoid extends Monoid _CommutativeMonoid(emptyValue, f); } -class _CommutativeMonoid extends CommutativeMonoid { +class _CommutativeMonoid + with + Semigroup, + CommutativeSemigroup, + Monoid, + CommutativeMonoid { final T emp; final T Function(T x, T y) comb; diff --git a/lib/src/typeclass/commutative_semigroup.dart b/lib/src/typeclass/commutative_semigroup.dart index e61ca980..7440f237 100644 --- a/lib/src/typeclass/commutative_semigroup.dart +++ b/lib/src/typeclass/commutative_semigroup.dart @@ -4,14 +4,14 @@ import 'package:fpdart/fpdart.dart'; /// /// A semigroup is [**commutative**](https://en.wikipedia.org/wiki/Commutative_property) /// if for all `x` and `y`, `combine(x, y) == combine(y, x)`. -abstract class CommutativeSemigroup extends Semigroup { +mixin CommutativeSemigroup on Semigroup { /// Create a `CommutativeSemigroup` instance from the given function. // ignore: library_private_types_in_public_api static _CommutativeSemigroup instance(A Function(A a1, A a2) f) => _CommutativeSemigroup(f); } -class _CommutativeSemigroup extends CommutativeSemigroup { +class _CommutativeSemigroup with Semigroup, CommutativeSemigroup { final T Function(T x, T y) comb; _CommutativeSemigroup(this.comb); diff --git a/lib/src/typeclass/extend.dart b/lib/src/typeclass/extend.dart index fdcd3c69..8c733974 100644 --- a/lib/src/typeclass/extend.dart +++ b/lib/src/typeclass/extend.dart @@ -2,7 +2,7 @@ import '../function.dart'; import 'functor.dart'; import 'hkt.dart'; -abstract class Extend extends HKT with Functor { +mixin Extend on HKT, Functor { /// Extend the type by applying function `f` to it. /// /// ```dart @@ -13,9 +13,7 @@ abstract class Extend extends HKT with Functor { HKT> duplicate() => extend(identity); } - -abstract class Extend2 extends HKT2 - with Functor2 { +mixin Extend2 on HKT2, Functor2 { /// Extend the type by applying function `f` to it. HKT2 extend(Z Function(HKT2 t) f); diff --git a/lib/src/typeclass/filterable.dart b/lib/src/typeclass/filterable.dart index 8033a88e..9cbc9cf4 100644 --- a/lib/src/typeclass/filterable.dart +++ b/lib/src/typeclass/filterable.dart @@ -5,7 +5,7 @@ import '../typedef.dart'; import 'functor.dart'; import 'hkt.dart'; -abstract class Filterable extends HKT with Functor { +mixin Filterable on HKT, Functor { /// Filter a data structure based on a boolean predicate. HKT filter(bool Function(A a) f); diff --git a/lib/src/typeclass/foldable.dart b/lib/src/typeclass/foldable.dart index 9861914a..899d036f 100644 --- a/lib/src/typeclass/foldable.dart +++ b/lib/src/typeclass/foldable.dart @@ -3,7 +3,7 @@ import '../tuple.dart'; import 'hkt.dart'; import 'monoid.dart'; -abstract class Foldable extends HKT { +mixin Foldable on HKT { B foldRight(B b, B Function(B acc, A a) f); B foldLeft(B b, B Function(B acc, A a) f) => @@ -46,7 +46,7 @@ abstract class Foldable extends HKT { HKT append(A t); } -abstract class Foldable2 extends HKT2 { +mixin Foldable2 on HKT2 { C foldRight(C b, C Function(C acc, B b) f); C foldLeft(C b, C Function(C acc, B b) f) => diff --git a/lib/src/typeclass/functor.dart b/lib/src/typeclass/functor.dart index 7a5f406e..08d4c21f 100644 --- a/lib/src/typeclass/functor.dart +++ b/lib/src/typeclass/functor.dart @@ -2,12 +2,12 @@ import 'hkt.dart'; /// `Functor extends HKT` to express the fact that the classes implementing /// the [Functor] interface will need to be higher kinded types. -abstract class Functor extends HKT { +mixin Functor on HKT { /// Return type is `HKT`, which expresses the fact that what /// we return is using exactly the same type constructor represented by the brand `G` HKT map(B Function(A a) f); } -abstract class Functor2 extends HKT2 { +mixin Functor2 on HKT2 { HKT2 map(C Function(B a) f); } diff --git a/lib/src/typeclass/group.dart b/lib/src/typeclass/group.dart index e1d0adf9..3f8ebc4b 100644 --- a/lib/src/typeclass/group.dart +++ b/lib/src/typeclass/group.dart @@ -1,7 +1,7 @@ import 'package:fpdart/fpdart.dart'; /// A group is a monoid where each element has an [**inverse**](https://en.wikipedia.org/wiki/Inverse_element). -abstract class Group extends Monoid { +mixin Group on Monoid { /// Find the inverse of `a`. /// /// `combine(a, inverse(a))` == `combine(inverse(a), a)` == `empty` @@ -39,7 +39,7 @@ abstract class Group extends Monoid { _Group(emptyValue, f, inv); } -class _Group extends Group { +class _Group with Semigroup, Monoid, Group { final T Function(T a) inv; final T emp; final T Function(T x, T y) comb; diff --git a/lib/src/typeclass/monad.dart b/lib/src/typeclass/monad.dart index 01b9584e..c013d0ba 100644 --- a/lib/src/typeclass/monad.dart +++ b/lib/src/typeclass/monad.dart @@ -1,7 +1,7 @@ import 'applicative.dart'; import 'hkt.dart'; -abstract class Monad extends HKT with Applicative { +mixin Monad on HKT, Applicative { HKT flatMap(HKT Function(A a) f); @override @@ -23,8 +23,7 @@ abstract class Monad extends HKT with Applicative { HKT call(HKT chain) => flatMap((_) => chain); } -abstract class Monad2 extends HKT2 - with Applicative2 { +mixin Monad2 on HKT2, Applicative2 { HKT2 flatMap(HKT2 Function(B a) f); /// Derive `ap` from `flatMap`. diff --git a/lib/src/typeclass/monoid.dart b/lib/src/typeclass/monoid.dart index ed4918b0..ff79c0c0 100644 --- a/lib/src/typeclass/monoid.dart +++ b/lib/src/typeclass/monoid.dart @@ -19,7 +19,7 @@ import 'semigroup.dart'; /// expect(instance.combine('abc', instance.empty), instance.combine(instance.empty, 'abc')); /// expect(instance.combine('abc', instance.empty), 'abc'); /// ``` -abstract class Monoid extends Semigroup { +mixin Monoid on Semigroup { /// Return the identity element for this monoid. T get empty; @@ -80,7 +80,7 @@ abstract class Monoid extends Semigroup { _Monoid(emptyValue, f); } -class _Monoid extends Monoid { +class _Monoid with Semigroup, Monoid { final T emp; final T Function(T x, T y) comb; diff --git a/lib/src/typeclass/semigroup.dart b/lib/src/typeclass/semigroup.dart index 0a6b0422..fcbdfa9f 100644 --- a/lib/src/typeclass/semigroup.dart +++ b/lib/src/typeclass/semigroup.dart @@ -1,7 +1,7 @@ /// A semigroup is any set `A` with an [**associative operation**](https://en.wikipedia.org/wiki/Associative_property) (`combine`). /// /// `(xy)z = x(yz) = xyz` for all `x`, `y`, `z` in `A` -abstract class Semigroup { +mixin Semigroup { /// Associative operation which combines two values. /// /// ```dart @@ -82,7 +82,7 @@ abstract class Semigroup { static Semigroup last() => _Semigroup((x, y) => y); } -class _Semigroup extends Semigroup { +class _Semigroup with Semigroup { final T Function(T x, T y) comb; _Semigroup(this.comb); diff --git a/lib/src/typeclass/semilattice.dart b/lib/src/typeclass/semilattice.dart index 6ed0f0c1..a19103bc 100644 --- a/lib/src/typeclass/semilattice.dart +++ b/lib/src/typeclass/semilattice.dart @@ -2,6 +2,7 @@ import 'band.dart'; import 'commutative_semigroup.dart'; import 'eq.dart'; import 'partial_order.dart'; +import 'semigroup.dart'; /// [**Semilattices**](https://en.wikipedia.org/wiki/Semilattice) /// are commutative semigroups whose operation @@ -16,7 +17,7 @@ import 'partial_order.dart'; /// > of the set `{x, y}` exists. /// /// See also [CommutativeSemigroup], [Bind]. -abstract class Semilattice extends Band with CommutativeSemigroup { +mixin Semilattice on Band, CommutativeSemigroup { /// Given `Eq`, return a `PartialOrder` using the `combine` /// operator of `Semilattice` to determine the partial ordering. This method assumes /// `combine` functions as `meet` (that is, as a **lower bound**). @@ -70,7 +71,8 @@ abstract class Semilattice extends Band with CommutativeSemigroup { _Semilattice(f); } -class _Semilattice extends Semilattice { +class _Semilattice + with Semigroup, CommutativeSemigroup, Band, Semilattice { final T Function(T x, T y) comb; _Semilattice(this.comb);