1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00

fix: add more examples

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
Dr. Carsten Leue
2023-09-05 22:51:46 +02:00
parent 5d77d5bb3d
commit 52b71ef4f3
4 changed files with 245 additions and 13 deletions

View File

@@ -131,7 +131,7 @@ func FromStrictCompare[A C.Ordered]() Ord[A] {
return MakeOrd(strictCompare[A], strictEq[A]) return MakeOrd(strictCompare[A], strictEq[A])
} }
// Lt tests whether one value is _strictly less than_ another // Lt tests whether one value is strictly less than another
func Lt[A any](O Ord[A]) func(A) func(A) bool { func Lt[A any](O Ord[A]) func(A) func(A) bool {
return func(second A) func(A) bool { return func(second A) func(A) bool {
return func(first A) bool { return func(first A) bool {
@@ -140,7 +140,7 @@ func Lt[A any](O Ord[A]) func(A) func(A) bool {
} }
} }
// Leq Tests whether one value is less or equal than_ another // Leq Tests whether one value is less or equal than another
func Leq[A any](O Ord[A]) func(A) func(A) bool { func Leq[A any](O Ord[A]) func(A) func(A) bool {
return func(second A) func(A) bool { return func(second A) func(A) bool {
return func(first A) bool { return func(first A) bool {
@@ -150,9 +150,9 @@ func Leq[A any](O Ord[A]) func(A) func(A) bool {
} }
/** /**
* Test whether one value is _strictly greater than_ another * Test whether one value is strictly greater than another
*/ */
func cc[A any](O Ord[A]) func(A) func(A) bool { func Gt[A any](O Ord[A]) func(A) func(A) bool {
return func(second A) func(A) bool { return func(second A) func(A) bool {
return func(first A) bool { return func(first A) bool {
return O.Compare(first, second) > 0 return O.Compare(first, second) > 0
@@ -160,7 +160,7 @@ func cc[A any](O Ord[A]) func(A) func(A) bool {
} }
} }
// Geq tests whether one value is greater or equal than_ another // Geq tests whether one value is greater or equal than another
func Geq[A any](O Ord[A]) func(A) func(A) bool { func Geq[A any](O Ord[A]) func(A) func(A) bool {
return func(second A) func(A) bool { return func(second A) func(A) bool {
return func(first A) bool { return func(first A) bool {

View File

@@ -19,9 +19,12 @@ import (
"fmt" "fmt"
"time" "time"
A "github.com/IBM/fp-go/array"
E "github.com/IBM/fp-go/either" E "github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/errors" "github.com/IBM/fp-go/errors"
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
I "github.com/IBM/fp-go/identity"
IOE "github.com/IBM/fp-go/ioeither"
N "github.com/IBM/fp-go/number" N "github.com/IBM/fp-go/number"
O "github.com/IBM/fp-go/option" O "github.com/IBM/fp-go/option"
"github.com/IBM/fp-go/ord" "github.com/IBM/fp-go/ord"
@@ -40,6 +43,45 @@ func getBalance(a Account) float32 {
return a.Balance return a.Balance
} }
type (
Chapter08User struct {
Id int
Name string
Active bool
Saved bool
}
)
var (
albert08 = Chapter08User{
Id: 1,
Active: true,
Name: "Albert",
}
gary08 = Chapter08User{
Id: 2,
Active: false,
Name: "Gary",
}
theresa08 = Chapter08User{
Id: 3,
Active: true,
Name: "Theresa",
}
yi08 = Chapter08User{Id: 4, Name: "Yi", Active: true}
)
func (u Chapter08User) getName() string {
return u.Name
}
func (u Chapter08User) isActive() bool {
return u.Active
}
var ( var (
ordFloat32 = ord.FromStrictCompare[float32]() ordFloat32 = ord.FromStrictCompare[float32]()
UpdateLedger = F.Identity[Account] UpdateLedger = F.Identity[Account]
@@ -55,6 +97,33 @@ var (
Withdraw(20), Withdraw(20),
O.Fold(F.Constant("You're broke!"), FinishTransaction), O.Fold(F.Constant("You're broke!"), FinishTransaction),
) )
// showWelcome :: User -> String
showWelcome = F.Flow2(
Chapter08User.getName,
S.Format[string]("Welcome %s"),
)
// checkActive :: User -> Either error User
checkActive = E.FromPredicate(Chapter08User.isActive, F.Constant1[Chapter08User](fmt.Errorf("Your account is not active")))
// validateUser :: (User -> Either String ()) -> User -> Either String User
validateUser = F.Curry2(func(validate func(Chapter08User) E.Either[error, any], user Chapter08User) E.Either[error, Chapter08User] {
return F.Pipe2(
user,
validate,
E.MapTo[error, any](user),
)
})
// save :: User -> IOEither error User
save = func(user Chapter08User) IOE.IOEither[error, Chapter08User] {
return IOE.FromIO[error](func() Chapter08User {
var u = user
u.Saved = true
return u
})
}
) )
func Withdraw(amount float32) func(account Account) O.Option[Account] { func Withdraw(amount float32) func(account Account) O.Option[Account] {
@@ -131,3 +200,77 @@ func Example_getAge() {
// Left[*time.ParseError, float64](parsing time "July 4, 2001" as "2006-01-02": cannot parse "July 4, 2001" as "2006") // Left[*time.ParseError, float64](parsing time "July 4, 2001" as "2006-01-02": cannot parse "July 4, 2001" as "2006")
// If you survive, you will be 6837 // If you survive, you will be 6837
} }
func Example_solution08A() {
incrF := I.Map(N.Add(1))
fmt.Println(incrF(I.Of(2)))
// Output: 3
}
func Example_solution08B() {
// initial :: User -> Option rune
initial := F.Flow3(
Chapter08User.getName,
S.ToRunes,
A.Head[rune],
)
fmt.Println(initial(albert08))
// Output:
// Some[int32](65)
}
func Example_solution08C() {
// eitherWelcome :: User -> Either String String
eitherWelcome := F.Flow2(
checkActive,
E.Map[error](showWelcome),
)
fmt.Println(eitherWelcome(gary08))
fmt.Println(eitherWelcome(theresa08))
// Output:
// Left[*errors.errorString, string](Your account is not active)
// Right[<nil>, string](Welcome Theresa)
}
func Example_solution08D() {
// // validateName :: User -> Either String ()
validateName := F.Flow3(
Chapter08User.getName,
E.FromPredicate(F.Flow2(
S.Size,
ord.Gt(ord.FromStrictCompare[int]())(3),
), errors.OnSome[string]("Your name %s is larger than 3 characters")),
E.Map[error](F.ToAny[string]),
)
saveAndWelcome := F.Flow2(
save,
IOE.Map[error](showWelcome),
)
register := F.Flow3(
validateUser(validateName),
IOE.FromEither[error, Chapter08User],
IOE.Chain(saveAndWelcome),
)
fmt.Println(validateName(gary08))
fmt.Println(validateName(yi08))
fmt.Println(register(albert08)())
fmt.Println(register(yi08)())
// Output:
// Right[<nil>, string](Gary)
// Left[*errors.errorString, <nil>](Your name Yi is larger than 3 characters)
// Right[<nil>, string](Welcome Albert)
// Left[*errors.errorString, string](Your name Yi is larger than 3 characters)
}

View File

@@ -17,10 +17,13 @@ package mostlyadequate
import ( import (
"fmt" "fmt"
"path"
A "github.com/IBM/fp-go/array" A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/io"
O "github.com/IBM/fp-go/option" O "github.com/IBM/fp-go/option"
S "github.com/IBM/fp-go/string"
) )
type ( type (
@@ -37,20 +40,70 @@ type (
AddressBook struct { AddressBook struct {
Addresses []Address Addresses []Address
} }
Chapter09User struct {
Id int
Name string
Address Address
}
) )
func getAddresses(ab AddressBook) []Address { var (
albert09 = Chapter09User{
Id: 1,
Name: "Albert",
Address: Address{
Street: Street{
Number: 22,
Name: "Walnut St",
},
},
}
gary09 = Chapter09User{
Id: 2,
Name: "Gary",
Address: Address{
Street: Street{
Number: 14,
},
},
}
theresa09 = Chapter09User{
Id: 3,
Name: "Theresa",
}
)
func (ab AddressBook) getAddresses() []Address {
return ab.Addresses return ab.Addresses
} }
func getStreet(s Address) Street { func (s Address) getStreet() Street {
return s.Street return s.Street
} }
var FirstAddressStreet = F.Flow3( func (s Street) getName() string {
getAddresses, return s.Name
A.Head[Address], }
O.Map(getStreet),
func (u Chapter09User) getAddress() Address {
return u.Address
}
var (
FirstAddressStreet = F.Flow3(
AddressBook.getAddresses,
A.Head[Address],
O.Map(Address.getStreet),
)
// getFile :: IO String
getFile = io.Of("/home/mostly-adequate/ch09.md")
// pureLog :: String -> IO ()
pureLog = io.Logf[string]("%s")
) )
func Example_street() { func Example_street() {
@@ -62,3 +115,35 @@ func Example_street() {
// Output: // Output:
// Some[mostlyadequate.Street]({Mulburry 8402}) // Some[mostlyadequate.Street]({Mulburry 8402})
} }
func Example_solution09A() {
// // getStreetName :: User -> Maybe String
getStreetName := F.Flow4(
Chapter09User.getAddress,
Address.getStreet,
Street.getName,
O.FromPredicate(S.IsNonEmpty),
)
fmt.Println(getStreetName(albert09))
fmt.Println(getStreetName(gary09))
fmt.Println(getStreetName(theresa09))
// Output:
// Some[string](Walnut St)
// None[string]
// None[string]
}
func Example_solution09B() {
logFilename := F.Flow2(
io.Map(path.Base),
io.ChainFirst(pureLog),
)
fmt.Println(logFilename(getFile)())
// Output:
// ch09.md
}

View File

@@ -20,7 +20,7 @@ import (
"strings" "strings"
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/ord" "github.com/IBM/fp-go/ord"
) )
var ( var (
@@ -31,7 +31,7 @@ var (
ToLowerCase = strings.ToLower ToLowerCase = strings.ToLower
// Ord implements the default ordering for strings // Ord implements the default ordering for strings
Ord = O.FromStrictCompare[string]() Ord = ord.FromStrictCompare[string]()
) )
func Eq(left string, right string) bool { func Eq(left string, right string) bool {
@@ -42,6 +42,10 @@ func ToBytes(s string) []byte {
return []byte(s) return []byte(s)
} }
func ToRunes(s string) []rune {
return []rune(s)
}
func IsEmpty(s string) bool { func IsEmpty(s string) bool {
return len(s) == 0 return len(s) == 0
} }