Created
November 4, 2022 21:43
-
-
Save patrickbucher/70b8f1ebe91ea2f50cb829c7bad657a7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
) | |
type Number float64 | |
type Operator func(Number) Number | |
func Adder(i Number) Operator { | |
return func(n Number) Number { | |
return n + i | |
} | |
} | |
func Subtractor(i Number) Operator { | |
return func(n Number) Number { | |
return n - i | |
} | |
} | |
func Multiplier(i Number) Operator { | |
return func(n Number) Number { | |
return n * i | |
} | |
} | |
func Divider(i Number) Operator { | |
return func(n Number) Number { | |
return n / i // FIXME: divide by zero | |
} | |
} | |
// f(g(n)) | |
func Compose(f, g Operator) Operator { | |
return func(n Number) Number { | |
x := g(n) | |
y := f(x) | |
return y | |
} | |
} | |
type Result struct { | |
Val Number | |
Err error | |
} | |
type LiftingOperator func(Number) Result | |
func LiftingAdder(i Number) LiftingOperator { | |
return func(n Number) Result { | |
return Result{n + i, nil} | |
} | |
} | |
func LiftingSubtractor(i Number) LiftingOperator { | |
return func(n Number) Result { | |
return Result{n - i, nil} | |
} | |
} | |
func LiftingMultiplier(i Number) LiftingOperator { | |
return func(n Number) Result { | |
return Result{n * i, nil} | |
} | |
} | |
func LiftingDivider(i Number) LiftingOperator { | |
return func(n Number) Result { | |
if i == 0 { | |
return Result{0.0, errors.New("divide by zero")} | |
} | |
return Result{n / i, nil} | |
} | |
} | |
func ComposeLifting(f, g LiftingOperator) LiftingOperator { | |
return func(n Number) Result { | |
x := g(n) | |
if x.Err != nil { | |
return Result{0.0, fmt.Errorf("call inner function: %w", x.Err)} | |
} | |
y := f(x.Val) | |
if y.Err != nil { | |
return Result{0.0, fmt.Errorf("call outer function: %w", y.Err)} | |
} | |
return Result{y.Val, nil} | |
} | |
} | |
func main() { | |
var n Number = 1 | |
addTwo := Adder(2) | |
subOne := Subtractor(1) | |
mulThree := Multiplier(3) | |
divFour := Divider(4) | |
// ((((1 + 2) * 3) - 1) / 4) = 2.0 | |
fmt.Println(divFour(subOne(mulThree(addTwo(n))))) | |
f := Compose(mulThree, addTwo) | |
g := Compose(subOne, f) | |
h := Compose(divFour, g) | |
fmt.Println(h(n)) | |
//divZero := Divider(0) | |
//f = Compose(mulThree, addTwo) | |
//g = Compose(subOne, f) | |
//h = Compose(divZero, g) // NOTE: this would break everything | |
//fmt.Println(h(n)) | |
addLiftingTwo := LiftingAdder(2) | |
subLiftingOne := LiftingSubtractor(1) | |
mulLiftingThree := LiftingMultiplier(3) | |
divLiftingFour := LiftingDivider(4) | |
fl := ComposeLifting(mulLiftingThree, addLiftingTwo) | |
gl := ComposeLifting(subLiftingOne, fl) | |
hl := ComposeLifting(divLiftingFour, gl) | |
fmt.Println(hl(n)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment