Closed screwyprof closed 3 years ago
Thank you for submitting such a detailed issue with great examples and references! I am so glad that you are interested in my project. I have done some experiments on Go generics these days and APIs are almost fixed. So I will be able to start writing some examples soon. Please wait for a moment!
Your functional FizzBuzz example can be written as something like this with dogs
(but there's still lack of some functions):
var monoid algebra.Monoid[option.Option[string]] = option.DeriveMonoid[string](algebra.DeriveMonoid[string]())
func FizzBuzz(i int) string {
return option.UnwrapOr(
monoid.Combine(
option.Filter(option.Some[string]("fizz"), func (_ string) bool { return i % 3 == 0 }),
option.Filter(option.Some[string]("buzz"), func (_ string) bool { return i % 5 == 0 }),
),
fmt.Sprint(i),
)
}
func main() {
iterator.ForEach[string](
iterator.Map[int, string](iterator.Range[int](1, 100), FizzBuzz),
func (x string) { fmt.Println(x) },
)
}
It's still a bit ugly compared to Haskell, but I think It's acceptable. I hope you will like this 😄
Sorry for being late, but I added the example above to the repo! https://github.com/genkami/dogs/tree/main/examples
Hello @genkami!
First of all thank you for this nice project. I've recently discovered it and find it interesting.
I wanted to send you a letter, but then thought, that this issue maybe useful to some other enthusiasts, and also I can use the markdown formatting. Apologies for a long read and for the fact that I haven't had the chance to push the project to GitHub yet.
Before the generics were available I was playing around Monoids in Golang. My favourite example is FizzBuzz!
So I implemented the solution which was highly inspired by a couple of articles mentioned bellow. The first approach looked something like this:
I had to implement an
Optional
type (an equivalent of Maybe, the name seemed more conventional for Golang).UnwrapOr
is basicallyFromMaybe
in Haskell. After that I turned thatOptional
into a monoid. The API is not ideal, but the solution looks pretty simple. Given that we don't have the monadic list comprehensions I usedFiltered
function to add the predicated. So basically the structure that implemented the monoid, also had aFiltered
method. Not very elegant, but better than nothing.The beauty of this solution is that we can easily add more predicates: Fizz, Buzz, Bizz, etc... However in order for it to work we need to be able to create a Monoid which is basically a function, and not a concrete a simple type.
My
Optional Monoid
looked like this:It was using a String Option which supported the Append for convenience, however it was not a Monoid, it didn't respect the Monodic laws, however the monoid.OptionsSting did:
The new iteration was changed a little to use foldable:
Now that we have the generics, and your library we probably can come up with a better solution. I tried to use some of your ideas but at the moment you're changing the API faster than I have the time to follow :-D Nonetheless, I was almost able to implement the monoids I need from your wonderful library, however I stuck at the moment with a monoid to combine two functions. It got pretty ugly on my side.
Could you please add an
ExampleTest
for thisFizzBuzz
case to demonstrate the usage of your library the way you were intended? What I really would like to achieve is the following translated into Go without being too ugly :)Thank you very much.