mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
187 lines
3.6 KiB
Go
187 lines
3.6 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.
|
|
|
|
package mostlyadequate
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"regexp"
|
|
|
|
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"
|
|
"github.com/IBM/fp-go/io"
|
|
IOE "github.com/IBM/fp-go/ioeither"
|
|
O "github.com/IBM/fp-go/option"
|
|
S "github.com/IBM/fp-go/string"
|
|
)
|
|
|
|
type (
|
|
Street struct {
|
|
Name string
|
|
Number int
|
|
}
|
|
|
|
Address struct {
|
|
Street Street
|
|
Postcode string
|
|
}
|
|
|
|
AddressBook struct {
|
|
Addresses []Address
|
|
}
|
|
|
|
Chapter09User struct {
|
|
Id int
|
|
Name string
|
|
Address 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 (s Address) getStreet() Street {
|
|
return s.Street
|
|
}
|
|
|
|
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")
|
|
|
|
// addToMailingList :: Email -> IOEither([Email])
|
|
addToMailingList = F.Flow2(
|
|
A.Of[string],
|
|
IOE.Of[error, []string],
|
|
)
|
|
|
|
// validateEmail :: Email -> Either error Email
|
|
validateEmail = E.FromPredicate(Matches(regexp.MustCompile(`\S+@\S+\.\S+`)), errors.OnSome[string]("email %s is invalid"))
|
|
|
|
// emailBlast :: [Email] -> IO ()
|
|
emailBlast = F.Flow2(
|
|
A.Intercalate(S.Monoid)(","),
|
|
IOE.Of[error, string],
|
|
)
|
|
)
|
|
|
|
func Example_street() {
|
|
s := FirstAddressStreet(AddressBook{
|
|
Addresses: A.From(Address{Street: Street{Name: "Mulburry", Number: 8402}, Postcode: "WC2N"}),
|
|
})
|
|
fmt.Println(s)
|
|
|
|
// 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
|
|
}
|
|
|
|
func Example_solution09C() {
|
|
|
|
// // joinMailingList :: Email -> Either String (IO ())
|
|
joinMailingList := F.Flow4(
|
|
validateEmail,
|
|
IOE.FromEither[error, string],
|
|
IOE.Chain(addToMailingList),
|
|
IOE.Chain(emailBlast),
|
|
)
|
|
|
|
fmt.Println(joinMailingList("sleepy@grandpa.net")())
|
|
fmt.Println(joinMailingList("notanemail")())
|
|
|
|
// Output:
|
|
// Right[<nil>, string](sleepy@grandpa.net)
|
|
// Left[*errors.errorString, string](email notanemail is invalid)
|
|
}
|