Skip to content

Commit

Permalink
doc: add examples and solutions from mostly adequate
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 3, 2023
1 parent 12a4f68 commit 8692078
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 8 deletions.
6 changes: 6 additions & 0 deletions number/magma.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ func MagmaSub[A Number]() M.Magma[A] {
return first - second
})
}

func MagmaDiv[A Number]() M.Magma[A] {
return M.MakeMagma(func(first A, second A) A {
return first / second
})
}
10 changes: 10 additions & 0 deletions number/monoid.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,20 @@ import (
M "github.com/IBM/fp-go/monoid"
)

// MonoidSum is the [Monoid] that adds elements with a zero empty element
func MonoidSum[A Number]() M.Monoid[A] {
s := SemigroupSum[A]()
return M.MakeMonoid(
s.Concat,
0,
)
}

// MonoidProduct is the [Monoid] that multiplies elements with a one empty element
func MonoidProduct[A Number]() M.Monoid[A] {
s := SemigroupProduct[A]()
return M.MakeMonoid(
s.Concat,
1,
)
}
6 changes: 6 additions & 0 deletions number/semigroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ func SemigroupSum[A Number]() S.Semigroup[A] {
return first + second
})
}

func SemigroupProduct[A Number]() S.Semigroup[A] {
return S.MakeSemigroup(func(first A, second A) A {
return first * second
})
}
26 changes: 20 additions & 6 deletions number/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,30 @@ type Number interface {
}

// Add is a curried function used to add two numbers
func Add[T Number](left T) func(T) T {
return func(right T) T {
func Add[T Number](right T) func(T) T {
return func(left T) T {
return left + right
}
}

// Mul is a curried function used to add two numbers
func Mul[T Number](coeff T) func(T) T {
return func(value T) T {
return coeff * value
// Sub is a curried function used to subtract two numbers
func Sub[T Number](right T) func(T) T {
return func(left T) T {
return left - right
}
}

// Mul is a curried function used to multiply two numbers
func Mul[T Number](right T) func(T) T {
return func(left T) T {
return left * right
}
}

// Div is a curried function used to divide two numbers
func Div[T Number](right T) func(T) T {
return func(left T) T {
return left / right
}
}

Expand Down
38 changes: 38 additions & 0 deletions samples/mostly-adequate/chapter02_firstclassfunctions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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"

func Hi(name string) string {
return fmt.Sprintf("Hi %s", name)
}

func Greeting(name string) string {
return Hi(name)
}

func Example_greeting() {
// functions are first class objects
greet := Hi

fmt.Println(Greeting("times"))
fmt.Println(greet("times"))

// Output:
// Hi times
// Hi times
}
41 changes: 39 additions & 2 deletions samples/mostly-adequate/chapter04_currying_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@
package mostlyadequate

import (
"fmt"
"math"
"regexp"
"strings"

A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function"
N "github.com/IBM/fp-go/number"
I "github.com/IBM/fp-go/number/integer"
S "github.com/IBM/fp-go/string"
)

var (
Match = F.Curry2((*regexp.Regexp).FindStringSubmatch)
Split = F.Curry2(F.Bind3of3((*regexp.Regexp).Split)(-1))
Match = F.Curry2((*regexp.Regexp).FindStringSubmatch)
Matches = F.Curry2((*regexp.Regexp).MatchString)
Split = F.Curry2(F.Bind3of3((*regexp.Regexp).Split)(-1))

Add = N.Add[int]
ToString = I.ToString
Expand All @@ -44,3 +48,36 @@ func Replace(search *regexp.Regexp) func(replace string) func(s string) string {
}
}
}

func Example_solution04A() {
// words :: String -> [String]
words := Split(regexp.MustCompile(` `))

fmt.Println(words("Jingle bells Batman smells"))

// Output:
// [Jingle bells Batman smells]
}

func Example_solution04B() {
// filterQs :: [String] -> [String]
filterQs := A.Filter(Matches(regexp.MustCompile(`q`)))

fmt.Println(filterQs(A.From("quick", "camels", "quarry", "over", "quails")))

// Output:
// [quick quarry quails]
}

func Example_solution04C() {

keepHighest := N.Max[int]

// max :: [Number] -> Number
max := A.Reduce(keepHighest, math.MinInt)

fmt.Println(max(A.From(323, 523, 554, 123, 5234)))

// Output:
// 5234
}
50 changes: 50 additions & 0 deletions samples/mostly-adequate/chapter05_composing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (

A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function"
I "github.com/IBM/fp-go/number/integer"
O "github.com/IBM/fp-go/option"
"github.com/IBM/fp-go/ord"
S "github.com/IBM/fp-go/string"
)

Expand Down Expand Up @@ -58,3 +61,50 @@ func Example_pipe() {

// Output: SEND IN THE CLOWNS!
}

func Example_solution05A() {
IsLastInStock := F.Flow2(
A.Last[Car],
O.Map(Car.getInStock),
)

fmt.Println(IsLastInStock(Cars[0:3]))
fmt.Println(IsLastInStock(Cars[3:]))

// Output:
// Some[bool](true)
// Some[bool](false)
}

func Example_solution05B() {
// averageDollarValue :: [Car] -> Int
averageDollarValue := F.Flow2(
A.Map(Car.getDollarValue),
average,
)

fmt.Println(averageDollarValue(Cars))

// Output:
// 790700
}

func Example_solution05C() {
// order by horsepower
ordByHorsepower := ord.Contramap(Car.getHorsepower)(I.Ord)

// fastestCar :: [Car] -> Option[String]
fastestCar := F.Flow3(
A.Sort(ordByHorsepower),
A.Last[Car],
O.Map(F.Flow2(
Car.getName,
S.Format[string]("%s is the fastest"),
)),
)

fmt.Println(fastestCar(Cars))

// Output:
// Some[string](Aston Martin One-77 is the fastest)
}
89 changes: 89 additions & 0 deletions samples/mostly-adequate/support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// 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 (
A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function"
N "github.com/IBM/fp-go/number"
)

type (
Car struct {
Name string
Horsepower int
DollarValue float32
InStock bool
}
)

func (car Car) getInStock() bool {
return car.InStock
}

func (car Car) getDollarValue() float32 {
return car.DollarValue
}

func (car Car) getHorsepower() int {
return car.Horsepower
}

func (car Car) getName() string {
return car.Name
}

func average(val []float32) float32 {
return F.Pipe2(
val,
A.Fold(N.MonoidSum[float32]()),
N.Div(float32(len(val))),
)
}

var (
Cars = A.From(Car{
Name: "Ferrari FF",
Horsepower: 660,
DollarValue: 700000,
InStock: true,
}, Car{
Name: "Spyker C12 Zagato",
Horsepower: 650,
DollarValue: 648000,
InStock: false,
}, Car{
Name: "Jaguar XKR-S",
Horsepower: 550,
DollarValue: 132000,
InStock: true,
}, Car{
Name: "Audi R8",
Horsepower: 525,
DollarValue: 114200,
InStock: false,
}, Car{
Name: "Aston Martin One-77",
Horsepower: 750,
DollarValue: 1850000,
InStock: true,
}, Car{
Name: "Pagani Huayra",
Horsepower: 700,
DollarValue: 1300000,
InStock: false,
})
)

0 comments on commit 8692078

Please sign in to comment.