-
Notifications
You must be signed in to change notification settings - Fork 47
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
Would a function family like BindNofVariadic()
be useful? | Chaining w/ inheritance
#38
Comments
Hi @a-lipson let's me comment on the second aspect, type problem first. func Pipe1[F1 ~func(T0) T1, T0, T1 any](t0 T0, f1 F1) T1 {
Since But as far as I know this is not possible in go, it would have to be something along these lines: func Pipe1[F1 ~func(B0) T1, B0 any, T0 ~B0, T1 any](t0 T0, f1 F1) T1 { trying to express that the starting type But this is unsupported. https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#no-way-to-express-convertibility The only workaround I am aware of is to write an explicit type conversion function and add that to the pipe. Not nice, but a mitigation. func (m MyType) AsThing() Thing { return m }
out1 := F.Pipe2(example, MyType.AsThing, ThingAction) The direct invocation You might ask if such an implicit type conversion could be a helper function in the library. I was actually not able to find a good solution, the signature would have to be something like: func ToType[A any, B ~A](b B) A {
return b
} But that is not possible. We could do func ToType[A, B any(b B) A {
return any(b).(A)
} but then you lose type safety and the pre-knowlege that So my best guess are custom type conversions of the form Do you have any ideas? |
On variadic function support. So far this is the train of thoughts:
A simple usecase using func fromLibrary(data ...string) string {
return strings.Join(data, "-")
}
func TestUnvariadic(t *testing.T) {
res := Pipe1(
[]string{"A", "B"},
Unvariadic0(fromLibrary),
)
assert.Equal(t, "A-B", res)
} From a naming perspective the naming |
How about this:
func Unsliced2[F ~func([]T) R, T, R any](f F) func(T, T) R {
return func(t1 T, t2 T) R {
return f([]T{t1, t2})
}
} and then we can use this in conjunction with func fromLibrary(data ...string) string {
return strings.Join(data, "-")
}
func Unsliced2[F ~func([]T) R, T, R any](f F) func(T, T) R {
return func(t1 T, t2 T) R {
return f([]T{t1, t2})
}
}
func TestVariadicArity(t *testing.T) {
f := Unsliced2(Unvariadic0(fromLibrary))
res := f("A", "B")
assert.Equal(t, "A-B", res)
} |
Hi @CarstenLeue, thank you very much for your explanations. I did not realize that the inheritance problem that I was encountering was the same as the variant/covariant data types. I am still learning. I think I have a better understanding of the problem now, and I can certainly see how it's perhaps not possible to do a convertibility check and the only workaround appears to be some sort of specific casting method or a loss of type-safety. I would prefer a boilerplate casting method as opposed to a loss of type safety. With regards to the variadics, as of my current understanding, it seems that Additionally, I will try testing composition of functions with multiple input parameters using the tuple functions. Once again, thank you! |
Please forgive me for creating this issue for creating this issue if this functionality is already possible with a composition of extant functions.
Nonetheless, let me describe the scenario I am working with.
I have a function from a library that takes a single variadic input. I have a pipeline of functions that eventually needs to put an item into this variadic function.
The current approach that I am taking is to pipe up to the last function and store that output, then to pass the output to the the library's function.
I have also taken a look at using the
Unvariadic0
function, but I think the method above is simpler.This leads me to wonder if functions that would take functions with variadic arguments and produce functions with a finite set of arguments would be helpful.
While looking for a way to accomplish this, I found the bind and ignore functions which are similar, but I don't fully understand them. Hence why I imagined that there probably exists a way to accomplish what I was trying to accomplish, yet I cannot see it.
I might implement the
BindNofVariadic
function like this,Then for two arguments,
One potential consideration would be the case where a function has its variadic argument in the second, third, fourth, etc. position. As is the case with the
UnvariadicN
family of functions.The minimal differences between
Bind1...
,Bind2...
andBindN...
suggest to me now that this functionality might be accomplished by some form ofUnvariadicN
and then some sort of indexing of the resulting slice.For example, if there were a family of slice builder functions from some data, like
FromN
, then one could go from the single value to aFrom1
to aUnvariadic0
on some functionf
. However, I think this might be just another version of the same proposed solution.Or perhaps this problem is indicative of some inherent design issue, rather than reason for a new function.
Another question that I have is about how chaining with inherited types works.
Here are two examples that I created to try to better understand.
and
Aside from this, I am enjoying trying to implement functional design patterns in my go project.
I am following the tutorials that you have linked (both Ryan Lee's blog and Professor Frisby's Mostly Adequate Guide to Functional Programming)
In addition, I am trying to learn Haskell and Category Theory (mainly following Bartosz Milewski's lectures on YouTube at the moment) to have a better understanding of the functional concepts before employing them in go.
Thank you very much for this resource and assistance!
The text was updated successfully, but these errors were encountered: