Skip to content

Commit

Permalink
fix: add more examples
Browse files Browse the repository at this point in the history
Signed-off-by: Dr. Carsten Leue <[email protected]>
  • Loading branch information
CarstenLeue committed Sep 5, 2023
1 parent 5d77d5b commit 52b71ef
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 13 deletions.
10 changes: 5 additions & 5 deletions ord/ord.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func FromStrictCompare[A C.Ordered]() Ord[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 {
return func(second A) func(A) bool {
return func(first A) bool {
Expand All @@ -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 {
return func(second A) func(A) bool {
return func(first A) bool {
Expand All @@ -150,17 +150,17 @@ 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(first A) bool {
return O.Compare(first, second) > 0
}
}
}

// 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 {
return func(second A) func(A) bool {
return func(first A) bool {
Expand Down
143 changes: 143 additions & 0 deletions samples/mostly-adequate/chapter08_tupperware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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]
Expand All @@ -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] {
Expand Down Expand Up @@ -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)
}
97 changes: 91 additions & 6 deletions samples/mostly-adequate/chapter09_monadiconions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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() {
Expand All @@ -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
}
8 changes: 6 additions & 2 deletions string/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"strings"

F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/ord"
"github.com/IBM/fp-go/ord"
)

var (
Expand All @@ -31,7 +31,7 @@ var (
ToLowerCase = strings.ToLower

// Ord implements the default ordering for strings
Ord = O.FromStrictCompare[string]()
Ord = ord.FromStrictCompare[string]()
)

func Eq(left string, right string) bool {
Expand All @@ -42,6 +42,10 @@ func ToBytes(s string) []byte {
return []byte(s)
}

func ToRunes(s string) []rune {
return []rune(s)
}

func IsEmpty(s string) bool {
return len(s) == 0
}
Expand Down

0 comments on commit 52b71ef

Please sign in to comment.