1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00
Files
fp-go/optics/iso/iso.go
Dr. Carsten Leue ff1b6faf84 fix: order of parameters in optics
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2023-09-10 21:49:44 +02:00

106 lines
2.5 KiB
Go

// 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.
// Iso is an optic which converts elements of type `S` into elements of type `A` without loss.
package iso
import (
F "github.com/IBM/fp-go/function"
)
type Iso[S, A any] struct {
Get func(s S) A
ReverseGet func(a A) S
}
func MakeIso[S, A any](get func(S) A, reverse func(A) S) Iso[S, A] {
return Iso[S, A]{Get: get, ReverseGet: reverse}
}
// Id returns an iso implementing the identity operation
func Id[S any]() Iso[S, S] {
return MakeIso(F.Identity[S], F.Identity[S])
}
// Compose combines an ISO with another ISO
func Compose[S, A, B any](ab Iso[A, B]) func(Iso[S, A]) Iso[S, B] {
return func(sa Iso[S, A]) Iso[S, B] {
return MakeIso(
F.Flow2(sa.Get, ab.Get),
F.Flow2(ab.ReverseGet, sa.ReverseGet),
)
}
}
// Reverse changes the order of parameters for an iso
func Reverse[S, A any](sa Iso[S, A]) Iso[A, S] {
return MakeIso(
sa.ReverseGet,
sa.Get,
)
}
func modify[S, A any](f func(A) A, sa Iso[S, A], s S) S {
return F.Pipe3(
s,
sa.Get,
f,
sa.ReverseGet,
)
}
// Modify applies a transformation
func Modify[S, A any](f func(A) A) func(Iso[S, A]) func(S) S {
return F.Curry3(modify[S, A])(f)
}
// Wrap wraps the value
func Unwrap[A, S any](s S) func(Iso[S, A]) A {
return func(sa Iso[S, A]) A {
return sa.Get(s)
}
}
// Unwrap unwraps the value
func Wrap[S, A any](a A) func(Iso[S, A]) S {
return func(sa Iso[S, A]) S {
return sa.ReverseGet(a)
}
}
// From wraps the value
func To[A, S any](s S) func(Iso[S, A]) A {
return Unwrap[A, S](s)
}
// To unwraps the value
func From[S, A any](a A) func(Iso[S, A]) S {
return Wrap[S](a)
}
func imap[S, A, B any](sa Iso[S, A], ab func(A) B, ba func(B) A) Iso[S, B] {
return MakeIso(
F.Flow2(sa.Get, ab),
F.Flow2(ba, sa.ReverseGet),
)
}
// IMap implements a bidirectional mapping of the transform
func IMap[S, A, B any](ab func(A) B, ba func(B) A) func(Iso[S, A]) Iso[S, B] {
return func(sa Iso[S, A]) Iso[S, B] {
return imap(sa, ab, ba)
}
}