1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-11-23 22:14:53 +02:00
Files
fp-go/v2/identity/doc.go
Carsten Leue 3385c705dc Implement v2 using type aliases (#141)
* fix: initial checkin of v2

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: slowly migrate IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate MonadTraverseArray and TraverseArray

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate traversal

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: complete migration of IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate ioeither

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: refactorY

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: next step in migration

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust IO generation code

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO methods

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO

* fix: convert iooption

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert a bit of reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: new build script

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: reformat

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: simplify

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust Pair to Haskell semantic

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: documentation and testcases

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some performance optimizations

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: remove coverage

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: better doc

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

---------

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:27:00 +01:00

272 lines
6.8 KiB
Go

// Copyright (c) 2023 - 2025 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 implements the Identity monad, the simplest possible monad.
# Overview
The Identity monad is a trivial monad that simply wraps a value without adding
any computational context. It's the identity element in the category of monads,
meaning it doesn't add any effects or behavior - it just passes values through.
While seemingly useless, the Identity monad serves several important purposes:
- As a baseline for understanding more complex monads
- For testing monad transformers
- As a default when no specific monad is needed
- For generic code that works with any monad
In this implementation, Identity[A] is simply represented as type A itself,
making it a zero-cost abstraction.
# Core Concepts
The Identity monad implements the standard monadic operations:
- Of: Wraps a value (identity function)
- Map: Transforms the wrapped value
- Chain (FlatMap): Chains computations
- Ap: Applies a wrapped function to a wrapped value
Since Identity adds no context, all these operations reduce to simple function
application.
# Basic Usage
Creating and transforming Identity values:
// Of wraps a value (but it's just the identity)
x := identity.Of(42)
// x is just 42
// Map transforms the value
doubled := identity.Map(func(n int) int {
return n * 2
})(x)
// doubled is 84
// Chain for monadic composition
result := identity.Chain(func(n int) int {
return n + 10
})(doubled)
// result is 94
# Functor Operations
Map transforms values:
import F "github.com/IBM/fp-go/v2/function"
// Simple mapping
result := F.Pipe1(
5,
identity.Map(func(n int) int { return n * n }),
)
// result is 25
// MapTo replaces with a constant
result := F.Pipe1(
"ignored",
identity.MapTo[string, int](100),
)
// result is 100
# Applicative Operations
Ap applies wrapped functions:
add := func(a int) func(int) int {
return func(b int) int {
return a + b
}
}
// Apply a curried function
result := F.Pipe1(
add(10),
identity.Ap[int, int](5),
)
// result is 15
# Monad Operations
Chain for sequential composition:
// Chain multiple operations
result := F.Pipe2(
10,
identity.Chain(func(n int) int { return n * 2 }),
identity.Chain(func(n int) int { return n + 5 }),
)
// result is 25
// ChainFirst executes for side effects but keeps original value
result := F.Pipe1(
42,
identity.ChainFirst(func(n int) string {
return fmt.Sprintf("Value: %d", n)
}),
)
// result is still 42
# Do Notation
The package provides "do notation" for imperative-style composition:
type Result struct {
X int
Y int
Sum int
}
result := F.Pipe3(
identity.Do(Result{}),
identity.Bind(
func(r Result) func(int) Result {
return func(x int) Result {
r.X = x
return r
}
},
func(Result) int { return 10 },
),
identity.Bind(
func(r Result) func(int) Result {
return func(y int) Result {
r.Y = y
return r
}
},
func(Result) int { return 20 },
),
identity.Let(
func(r Result) func(int) Result {
return func(sum int) Result {
r.Sum = sum
return r
}
},
func(r Result) int { return r.X + r.Y },
),
)
// result is Result{X: 10, Y: 20, Sum: 30}
# Sequence and Traverse
Convert tuples of Identity values:
import T "github.com/IBM/fp-go/v2/tuple"
// Sequence a tuple
tuple := T.MakeTuple2(1, 2)
result := identity.SequenceTuple2(tuple)
// result is T.Tuple2[int, int]{1, 2}
// Traverse with transformation
tuple := T.MakeTuple2(1, 2)
result := identity.TraverseTuple2(
func(n int) int { return n * 2 },
func(n int) int { return n * 3 },
)(tuple)
// result is T.Tuple2[int, int]{2, 6}
# Monad Interface
Get a monad instance for generic code:
m := identity.Monad[int, string]()
// Use monad operations
value := m.Of(42)
mapped := m.Map(func(n int) string {
return fmt.Sprintf("Number: %d", n)
})(value)
# Why Identity?
The Identity monad might seem pointless, but it's useful for:
1. Testing: Test monad transformers with a simple base monad
2. Defaults: Provide a default when no specific monad is needed
3. Learning: Understand monad laws without additional complexity
4. Abstraction: Write generic code that works with any monad
Example of generic code:
func ProcessWithMonad[M any](
monad monad.Monad[int, string, M, M, func(int) M],
value int,
) M {
return F.Pipe2(
monad.Of(value),
monad.Map(func(n int) int { return n * 2 }),
monad.Map(func(n int) string { return fmt.Sprintf("%d", n) }),
)
}
// Works with Identity
result := ProcessWithMonad(identity.Monad[int, string](), 21)
// result is "42"
# Type Alias
The package defines:
type Operator[A, B any] = func(A) B
This represents an Identity computation from A to B, which is just a function.
# Functions
Core operations:
- Of[A any](A) A - Wrap a value (identity)
- Map[A, B any](func(A) B) func(A) B - Transform value
- Chain[A, B any](func(A) B) func(A) B - Monadic bind
- Ap[B, A any](A) func(func(A) B) B - Apply function
Monad variants:
- MonadMap, MonadChain, MonadAp - Uncurried versions
Additional operations:
- MapTo[A, B any](B) func(A) B - Replace with constant
- ChainFirst[A, B any](func(A) B) func(A) A - Execute for effect
- Flap[B, A any](A) func(func(A) B) B - Flip application
Do notation:
- Do[S any](S) S - Initialize context
- Bind[S1, S2, T any] - Bind computation result
- Let[S1, S2, T any] - Bind pure value
- LetTo[S1, S2, B any] - Bind constant
- BindTo[S1, T any] - Initialize from value
- ApS[S1, S2, T any] - Apply in context
Sequence/Traverse:
- SequenceT1-10 - Sequence tuples of size 1-10
- SequenceTuple1-10 - Sequence tuple types
- TraverseTuple1-10 - Traverse with transformations
Monad instance:
- Monad[A, B any]() - Get monad interface
# Related Packages
- function: Function composition utilities
- monad: Monad interface definition
- tuple: Tuple types for sequence operations
*/
package identity
//go:generate go run .. identity --count 10 --filename gen.go