From 02ec50c91d706c7df9ef068fd748ebe6d27306ec Mon Sep 17 00:00:00 2001 From: "Dr. Carsten Leue" Date: Mon, 5 Feb 2024 12:29:45 +0100 Subject: [PATCH] fix: attempt to expose Monad as an interface Signed-off-by: Dr. Carsten Leue --- array/generic/monad.go | 43 +++++++++++++++++++++++++++ array/monad.go | 26 +++++++++++++++++ either/monad.go | 43 +++++++++++++++++++++++++++ identity/monad.go | 43 +++++++++++++++++++++++++++ internal/applicative/types.go | 26 +++++++++++++++++ internal/apply/types.go | 25 ++++++++++++++++ internal/chain/types.go | 25 ++++++++++++++++ internal/functor/types.go | 20 +++++++++++++ internal/monad/monad.go | 26 +++++++++++++++++ internal/pointed/types.go | 21 ++++++++++++++ io/generic/monad.go | 43 +++++++++++++++++++++++++++ io/monad.go | 26 +++++++++++++++++ iterator/stateless/generic/monad.go | 45 +++++++++++++++++++++++++++++ iterator/stateless/monad.go | 26 +++++++++++++++++ option/monad.go | 43 +++++++++++++++++++++++++++ 15 files changed, 481 insertions(+) create mode 100644 array/generic/monad.go create mode 100644 array/monad.go create mode 100644 either/monad.go create mode 100644 identity/monad.go create mode 100644 internal/applicative/types.go create mode 100644 internal/apply/types.go create mode 100644 internal/chain/types.go create mode 100644 internal/functor/types.go create mode 100644 internal/monad/monad.go create mode 100644 internal/pointed/types.go create mode 100644 io/generic/monad.go create mode 100644 io/monad.go create mode 100644 iterator/stateless/generic/monad.go create mode 100644 iterator/stateless/monad.go create mode 100644 option/monad.go diff --git a/array/generic/monad.go b/array/generic/monad.go new file mode 100644 index 0000000..7a65b95 --- /dev/null +++ b/array/generic/monad.go @@ -0,0 +1,43 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package generic + +import ( + "github.com/IBM/fp-go/internal/monad" +) + +type arrayMonad[A, B any, GA ~[]A, GB ~[]B, GAB ~[]func(A) B] struct{} + +func (o *arrayMonad[A, B, GA, GB, GAB]) Of(a A) GA { + return Of[GA, A](a) +} + +func (o *arrayMonad[A, B, GA, GB, GAB]) Map(f func(A) B) func(GA) GB { + return Map[GA, GB, A, B](f) +} + +func (o *arrayMonad[A, B, GA, GB, GAB]) Chain(f func(A) GB) func(GA) GB { + return Chain[GA, GB, A, B](f) +} + +func (o *arrayMonad[A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB { + return Ap[GB, GAB, GA, B, A](fa) +} + +// Monad implements the monadic operations for an array +func Monad[A, B any, GA ~[]A, GB ~[]B, GAB ~[]func(A) B]() monad.Monad[A, B, GA, GB, GAB] { + return &arrayMonad[A, B, GA, GB, GAB]{} +} diff --git a/array/monad.go b/array/monad.go new file mode 100644 index 0000000..270316b --- /dev/null +++ b/array/monad.go @@ -0,0 +1,26 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + G "github.com/IBM/fp-go/array/generic" + "github.com/IBM/fp-go/internal/monad" +) + +// Monad returns the monadic operations for an array +func Monad[A, B any]() monad.Monad[A, B, []A, []B, []func(A) B] { + return G.Monad[A, B, []A, []B, []func(A) B]() +} diff --git a/either/monad.go b/either/monad.go new file mode 100644 index 0000000..7c12eca --- /dev/null +++ b/either/monad.go @@ -0,0 +1,43 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package either + +import ( + "github.com/IBM/fp-go/internal/monad" +) + +type eitherMonad[E, A, B any] struct{} + +func (o *eitherMonad[E, A, B]) Of(a A) Either[E, A] { + return Of[E, A](a) +} + +func (o *eitherMonad[E, A, B]) Map(f func(A) B) func(Either[E, A]) Either[E, B] { + return Map[E, A, B](f) +} + +func (o *eitherMonad[E, A, B]) Chain(f func(A) Either[E, B]) func(Either[E, A]) Either[E, B] { + return Chain[E, A, B](f) +} + +func (o *eitherMonad[E, A, B]) Ap(fa Either[E, A]) func(Either[E, func(A) B]) Either[E, B] { + return Ap[B, E, A](fa) +} + +// Monad implements the monadic operations for [Either] +func Monad[E, A, B any]() monad.Monad[A, B, Either[E, A], Either[E, B], Either[E, func(A) B]] { + return &eitherMonad[E, A, B]{} +} diff --git a/identity/monad.go b/identity/monad.go new file mode 100644 index 0000000..27c1d81 --- /dev/null +++ b/identity/monad.go @@ -0,0 +1,43 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package identity + +import ( + "github.com/IBM/fp-go/internal/monad" +) + +type identityMonad[A, B any] struct{} + +func (o *identityMonad[A, B]) Of(a A) A { + return Of[A](a) +} + +func (o *identityMonad[A, B]) Map(f func(A) B) func(A) B { + return Map[A, B](f) +} + +func (o *identityMonad[A, B]) Chain(f func(A) B) func(A) B { + return Chain[A, B](f) +} + +func (o *identityMonad[A, B]) Ap(fa A) func(func(A) B) B { + return Ap[B, A](fa) +} + +// Monad implements the monadic operations for [Option] +func Monad[A, B any]() monad.Monad[A, B, A, B, func(A) B] { + return &identityMonad[A, B]{} +} diff --git a/internal/applicative/types.go b/internal/applicative/types.go new file mode 100644 index 0000000..589fc6e --- /dev/null +++ b/internal/applicative/types.go @@ -0,0 +1,26 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package applicative + +import ( + "github.com/IBM/fp-go/internal/apply" + "github.com/IBM/fp-go/internal/pointed" +) + +type Applicative[A, B, HKTA, HKTB, HKTFAB any] interface { + apply.Apply[A, B, HKTA, HKTB, HKTFAB] + pointed.Pointed[A, HKTA] +} diff --git a/internal/apply/types.go b/internal/apply/types.go new file mode 100644 index 0000000..d42417e --- /dev/null +++ b/internal/apply/types.go @@ -0,0 +1,25 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apply + +import ( + "github.com/IBM/fp-go/internal/functor" +) + +type Apply[A, B, HKTA, HKTB, HKTFAB any] interface { + functor.Functor[A, B, HKTA, HKTB] + Ap(HKTA) func(HKTFAB) HKTB +} diff --git a/internal/chain/types.go b/internal/chain/types.go new file mode 100644 index 0000000..0d643f2 --- /dev/null +++ b/internal/chain/types.go @@ -0,0 +1,25 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package chain + +import ( + "github.com/IBM/fp-go/internal/apply" +) + +type Chainable[A, B, HKTA, HKTB, HKTFAB any] interface { + apply.Apply[A, B, HKTA, HKTB, HKTFAB] + Chain(func(A) HKTB) func(HKTA) HKTB +} diff --git a/internal/functor/types.go b/internal/functor/types.go new file mode 100644 index 0000000..022cde8 --- /dev/null +++ b/internal/functor/types.go @@ -0,0 +1,20 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package functor + +type Functor[A, B, HKTA, HKTB any] interface { + Map(func(A) B) func(HKTA) HKTB +} diff --git a/internal/monad/monad.go b/internal/monad/monad.go new file mode 100644 index 0000000..cbb5938 --- /dev/null +++ b/internal/monad/monad.go @@ -0,0 +1,26 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package monad + +import ( + "github.com/IBM/fp-go/internal/applicative" + "github.com/IBM/fp-go/internal/chain" +) + +type Monad[A, B, HKTA, HKTB, HKTFAB any] interface { + applicative.Applicative[A, B, HKTA, HKTB, HKTFAB] + chain.Chainable[A, B, HKTA, HKTB, HKTFAB] +} diff --git a/internal/pointed/types.go b/internal/pointed/types.go new file mode 100644 index 0000000..944692a --- /dev/null +++ b/internal/pointed/types.go @@ -0,0 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pointed + +type Pointed[A, HKTA any] interface { + // Of lifts a value into its higher kinded type + Of(A) HKTA +} diff --git a/io/generic/monad.go b/io/generic/monad.go new file mode 100644 index 0000000..46826a6 --- /dev/null +++ b/io/generic/monad.go @@ -0,0 +1,43 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package generic + +import ( + "github.com/IBM/fp-go/internal/monad" +) + +type ioMonad[A, B any, GA ~func() A, GB ~func() B, GAB ~func() func(A) B] struct{} + +func (o *ioMonad[A, B, GA, GB, GAB]) Of(a A) GA { + return Of[GA, A](a) +} + +func (o *ioMonad[A, B, GA, GB, GAB]) Map(f func(A) B) func(GA) GB { + return Map[GA, GB, A, B](f) +} + +func (o *ioMonad[A, B, GA, GB, GAB]) Chain(f func(A) GB) func(GA) GB { + return Chain[GA, GB, A, B](f) +} + +func (o *ioMonad[A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB { + return Ap[GB, GAB, GA, B, A](fa) +} + +// Monad implements the monadic operations for [Option] +func Monad[A, B any, GA ~func() A, GB ~func() B, GAB ~func() func(A) B]() monad.Monad[A, B, GA, GB, GAB] { + return &ioMonad[A, B, GA, GB, GAB]{} +} diff --git a/io/monad.go b/io/monad.go new file mode 100644 index 0000000..0825c90 --- /dev/null +++ b/io/monad.go @@ -0,0 +1,26 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package io + +import ( + "github.com/IBM/fp-go/internal/monad" + G "github.com/IBM/fp-go/io/generic" +) + +// Monad returns the monadic operations for [IO] +func Monad[A, B any]() monad.Monad[A, B, IO[A], IO[B], IO[func(A) B]] { + return G.Monad[A, B, IO[A], IO[B], IO[func(A) B]]() +} diff --git a/iterator/stateless/generic/monad.go b/iterator/stateless/generic/monad.go new file mode 100644 index 0000000..6877310 --- /dev/null +++ b/iterator/stateless/generic/monad.go @@ -0,0 +1,45 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package generic + +import ( + "github.com/IBM/fp-go/internal/monad" + O "github.com/IBM/fp-go/option" + T "github.com/IBM/fp-go/tuple" +) + +type iteratorMonad[A, B any, GA ~func() O.Option[T.Tuple2[GA, A]], GB ~func() O.Option[T.Tuple2[GB, B]], GAB ~func() O.Option[T.Tuple2[GAB, func(A) B]]] struct{} + +func (o *iteratorMonad[A, B, GA, GB, GAB]) Of(a A) GA { + return Of[GA, A](a) +} + +func (o *iteratorMonad[A, B, GA, GB, GAB]) Map(f func(A) B) func(GA) GB { + return Map[GB, GA, func(A) B, A, B](f) +} + +func (o *iteratorMonad[A, B, GA, GB, GAB]) Chain(f func(A) GB) func(GA) GB { + return Chain[GB, GA, A, B](f) +} + +func (o *iteratorMonad[A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB { + return Ap[GAB, GB, GA, A, B](fa) +} + +// Monad implements the monadic operations for iterators +func Monad[A, B any, GA ~func() O.Option[T.Tuple2[GA, A]], GB ~func() O.Option[T.Tuple2[GB, B]], GAB ~func() O.Option[T.Tuple2[GAB, func(A) B]]]() monad.Monad[A, B, GA, GB, GAB] { + return &iteratorMonad[A, B, GA, GB, GAB]{} +} diff --git a/iterator/stateless/monad.go b/iterator/stateless/monad.go new file mode 100644 index 0000000..833c7d3 --- /dev/null +++ b/iterator/stateless/monad.go @@ -0,0 +1,26 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stateless + +import ( + "github.com/IBM/fp-go/internal/monad" + G "github.com/IBM/fp-go/iterator/stateless/generic" +) + +// Monad returns the monadic operations for an [Iterator] +func Monad[A, B any]() monad.Monad[A, B, Iterator[A], Iterator[B], Iterator[func(A) B]] { + return G.Monad[A, B, Iterator[A], Iterator[B], Iterator[func(A) B]]() +} diff --git a/option/monad.go b/option/monad.go new file mode 100644 index 0000000..e503465 --- /dev/null +++ b/option/monad.go @@ -0,0 +1,43 @@ +// Copyright (c) 2024 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package option + +import ( + "github.com/IBM/fp-go/internal/monad" +) + +type optionMonad[A, B any] struct{} + +func (o *optionMonad[A, B]) Of(a A) Option[A] { + return Of[A](a) +} + +func (o *optionMonad[A, B]) Map(f func(A) B) func(Option[A]) Option[B] { + return Map[A, B](f) +} + +func (o *optionMonad[A, B]) Chain(f func(A) Option[B]) func(Option[A]) Option[B] { + return Chain[A, B](f) +} + +func (o *optionMonad[A, B]) Ap(fa Option[A]) func(Option[func(A) B]) Option[B] { + return Ap[B, A](fa) +} + +// Monad implements the monadic operations for [Option] +func Monad[A, B any]() monad.Monad[A, B, Option[A], Option[B], Option[func(A) B]] { + return &optionMonad[A, B]{} +}