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

@@ -19,9 +19,12 @@ import (
"fmt"
"time"
A "github.com/IBM/fp-go/array"
E "github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/errors"
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"
O "github.com/IBM/fp-go/option"
"github.com/IBM/fp-go/ord"
@@ -40,6 +43,45 @@ func getBalance(a Account) float32 {
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 (
ordFloat32 = ord.FromStrictCompare[float32]()
UpdateLedger = F.Identity[Account]
@@ -55,6 +97,33 @@ var (
Withdraw(20),
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] {
@@ -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")
// 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 (
"fmt"
"path"
A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/io"
O "github.com/IBM/fp-go/option"
S "github.com/IBM/fp-go/string"
)
type (
@@ -37,20 +40,70 @@ type (
AddressBook struct {
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
}
func getStreet(s Address) Street {
func (s Address) getStreet() Street {
return s.Street
}
var FirstAddressStreet = F.Flow3(
getAddresses,
A.Head[Address],
O.Map(getStreet),
func (s Street) getName() string {
return s.Name
}
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() {
@@ -62,3 +115,35 @@ func Example_street() {
// Output:
// 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
}