Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add primitive interfaces #15

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions HTK/HKT.go
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
package HTK

type HKT[T, U any] interface {
Unwrap() T
}
6 changes: 3 additions & 3 deletions fold/fold.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package collection_utils
package fold

func FoldLeft[T any](coll []T, op func(T, T) T, initial T) T {
func Left[T any](coll []T, op func(T, T) T, initial T) T {
for _, x := range coll {
initial = op(initial, x)
}
Expand All @@ -9,7 +9,7 @@ func FoldLeft[T any](coll []T, op func(T, T) T, initial T) T {
return initial
}

func FoldRight[T any](coll []T, op func(T, T) T, initial T) T {
func Right[T any](coll []T, op func(T, T) T, initial T) T {
for i := len(coll) - 1; i >= 0; i-- {
initial = op(coll[i], initial)
}
Expand Down
10 changes: 5 additions & 5 deletions fold/fold_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package collection_utils
package fold

import "testing"

Expand Down Expand Up @@ -35,9 +35,9 @@ func TestFoldLeft(t *testing.T) {

for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
got := FoldLeft(tc.coll, op, tc.x)
got := Left(tc.coll, op, tc.x)
if got != tc.want {
t.Errorf("FoldLeft(%v, %v, %v) = %v; want %v", tc.coll, "op", tc.x, got, tc.want)
t.Errorf("Left(%v, %v, %v) = %v; want %v", tc.coll, "op", tc.x, got, tc.want)
}
})
}
Expand Down Expand Up @@ -76,9 +76,9 @@ func TestFoldRight(t *testing.T) {

for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
got := FoldRight(tc.coll, op, tc.x)
got := Right(tc.coll, op, tc.x)
if got != tc.want {
t.Errorf("FoldRight(%v, %v, %v) = %v; want %v", tc.coll, "op", tc.x, got, tc.want)
t.Errorf("Right(%v, %v, %v) = %v; want %v", tc.coll, "op", tc.x, got, tc.want)
}
})
}
Expand Down
28 changes: 5 additions & 23 deletions functor/functor.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
package functor

type IFunctor[T any] interface {
Map(T) T
}

type Functor[T any] struct {
Val T
}

func Lift[T any, U any](f func(T) U) func(Functor[T]) Functor[U] {
return func(fa Functor[T]) Functor[U] {
return Functor[U]{
Val: f(fa.Val),
}
}
}
import "github.com/medmouine/gomad/HTK"

func Map[T any, U any](fa Functor[T], f func(T) U) Functor[U] {
return Functor[U]{
Val: f(fa.Val),
}
type Functor[T, U any] interface {
HTK.HKT[T, U]
}

func (fa Functor[T]) Map(f func(T) T) Functor[T] {
return Functor[T]{
Val: f(fa.Val),
}
type functor[T, U any] struct {
Functor[T, U]
}
68 changes: 0 additions & 68 deletions functor/functor_test.go

This file was deleted.

21 changes: 19 additions & 2 deletions identity/identity.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
package identity

func Identity[T any](i T) T {
return i
type Identity[T any] interface {
Bind(func(T) Identity[T]) Identity[T]
Unwrap() T
}

type identity[T any] struct {
v T
}

func Of[T any](v T) Identity[T] {
return &identity[T]{v}
}

func (i *identity[T]) Bind(f func(T) Identity[T]) Identity[T] {
return f(i.v)
}

func (i *identity[T]) Unwrap() T {
return i.v
}
29 changes: 29 additions & 0 deletions identity/identity_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
package identity

import "testing"

func TestOf(t *testing.T) {
identity := Of[string]("hello")
result := identity.Unwrap()
if result != "hello" {
t.Errorf("Expected 'hello', got '%s'", result)
}
}

func TestBind(t *testing.T) {
identity1 := Of[string]("hello")
identity2 := identity1.Bind(func(s string) Identity[string] {
return Of[string](s + " world")
})
result := identity2.Unwrap()
if result != "hello world" {
t.Errorf("Expected 'hello world', got '%s'", result)
}
}

func TestValue(t *testing.T) {
identity := Of[string]("hello")
result := identity.Unwrap()
if result != "hello" {
t.Errorf("Expected 'hello', got '%s'", result)
}
}
41 changes: 11 additions & 30 deletions io/io.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
package io

type IO[T any] interface {
Call() T
Map(f func(T) T) IO[T]
Run() T
Bind(func(T) IO[T]) IO[T]
}

type io[T any] struct {
IO[T]
f func() T
v T
f func()
}

func Of[T any](t T) IO[T] {
return io[T]{
f: func() T {
return t
},
}
func Of[T any](v T, f func()) IO[T] {
return &io[T]{v: v, f: f}
}

func From[T any](f func() T) IO[T] {
return io[T]{
f: f,
}
func (io io[T]) Run() T {
io.f()
return io.v
}

func Map[T any, U any](io IO[T], fn func(T) U) IO[U] {
f := func() U {
return fn(io.Call())
}
return From(f)
}

func (i io[T]) Call() T {
return i.f()
}

func (i io[T]) Map(fn func(T) T) IO[T] {
f := func() T {
return fn(i.Call())
}
return From(f)
func (io io[T]) Bind(f func(T) IO[T]) IO[T] {
return f(io.v)
}
59 changes: 23 additions & 36 deletions io/io_test.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,40 @@
package io

import (
"reflect"
"testing"
)

func TestOf(t *testing.T) {
got := Of("foo")

if !reflect.DeepEqual(got.Call(), "foo") {
t.Errorf("Of(\"foo\") = %v, want %v", got.Call(), "foo")
var printed bool
io := Of[string]("hello", func() { printed = true })
result := io.Run()
if result != "hello" {
t.Errorf("Expected 'hello', got '%s'", result)
}
}

func TestFrom(t *testing.T) {
fn := func() string {
return "foo"
}
got := From(fn)

if !reflect.DeepEqual(got.Call(), "foo") {
t.Errorf("From() = %v, want %v", got, "foo")
if !printed {
t.Error("Expected side effect to be executed")
}
}

func TestMap(t *testing.T) {
fn1 := func() string {
return "foo"
}
fn2 := func(s string) int {
return len(s)
}
got := Map(From(fn1), fn2)

if !reflect.DeepEqual(got.Call(), 3) {
t.Errorf("Map() = %v, want %v", got.Call(), 3)
func TestBind(t *testing.T) {
io1 := Of[string]("hello", func() {})
io2 := io1.Bind(func(s string) IO[string] {
return Of[string](s+" world", func() {})
})
result := io2.Run()
if result != "hello world" {
t.Errorf("Expected 'hello world', got '%s'", result)
}
}

func Test_io_Map(t *testing.T) {
fn1 := func() string {
return "foo"
func TestRun(t *testing.T) {
var printed bool
io := Of[string]("hello", func() { printed = true })
result := io.Run()
if result != "hello" {
t.Errorf("Expected 'hello', got '%s'", result)
}
fn2 := func(s string) string {
return s + "bar"
}
got := From(fn1).Map(fn2)

if !reflect.DeepEqual(got.Call(), "foobar") {
t.Errorf("Map() = %v, want %v", got.Call(), "foobar")
if !printed {
t.Error("Expected side effect to be executed")
}
}
19 changes: 19 additions & 0 deletions magma/magma.go
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
package magma

import "github.com/medmouine/gomad/fold"

type Magma[T any] interface {
Concat(T) T
}

type magma[T any] struct {
values []T
op func(T, T) T
}

func Of[T any](values []T, op func(T, T) T) Magma[T] {
return &magma[T]{values: values, op: op}
}

func (m magma[T]) Concat(x T) T {
return fold.Left(m.values, m.op, x)
}
Loading