Comments (4)
Hi @a-lipson
let's me comment on the second aspect, type problem first.
I have no good solution, I'd be grateful for any idea. From my perspective the issue is that in go there is no way to define covariant data types, all types are invariant. For your Thing
problem you use the F.Pipe1
method which is defined as:
func Pipe1[F1 ~func(T0) T1, T0, T1 any](t0 T0, f1 F1) T1 {
T0
isMyType
T1
isint
F1
isfunc(MyType)int
ThingAction
isfunc(Thing) int
Since MyType
is not identical to Thing
this does not work. In fact the signature of Pipe1
is too strict, what I would have liked to express is that F1
takes an argument of a type that is assignable from T0
.
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 t0 T0
has B0
as its base type and this is the type that the function expects. In Java you would e.g. use T0 extends B0
for this purpose.
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 ThingAction(example)
does support covariant type support though. 🤷
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 A
and B
are related.
So my best guess are custom type conversions of the form func (m MyType) AsThing() Thing { return m }
Do you have any ideas?
from fp-go.
On variadic function support. So far this is the train of thoughts:
- variadic arguments are always the last arguments in a function signature. So the set of
UnvariadicN
methods takes a function withN
non-variadic arguments and adds aN+1st
that represents the array(slice) of the variadic arguments - the set of
BindNofM
functions is meant to reduce the arity of aM
ary function by pinning down (binding) the some of the parameters to static values - the composition functions
PipeN
andFlowN
work on unary functions, i.e. one input one output - if you want to use a function taking more than one parameter in a composition, then the idea is to wrap the parameters into a single "wrapper" and pass that wrapper as a single argument.
- if all parameters are of the same type you can use an array and
A.From
- if the parameters are of different types, use a tutple and
T.MakeTupleN
andTupledN/UntupledN
- if all parameters are of the same type you can use an array and
A simple usecase using Unvariadic0
would be
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 func Bind1ofVariadic[T, R any](f func(...T) R) func(T) R {
does not really fit the naming of the existing Bind
functions, since for the existing ones the set of numbers after Bind
identities the indexes of the parameters to pin down. In Bind1ofVariadic
the 1
is rather the arity of the resulting function.
from fp-go.
How about this:
- we add a function similar to
UntupledN
but for slices, e.g.
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 Unvariadic0
like so:
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)
}
from fp-go.
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 UnslicedN
would be a helpful series of functions.
However, I think that I need to learn more about currying and composition of curried functions in order to find different approaches to the same issue. So, I would defer to your much much more experienced opinion if such a function family would be both useful, but, more importantly I'd imagine, conducive to writing good code.
Additionally, I will try testing composition of functions with multiple input parameters using the tuple functions.
Once again, thank you!
from fp-go.
Related Issues (12)
- Running tests using gotip is failing HOT 1
- Learning fp-go question HOT 2
- Questions & Comments on differences between Pipe and Flow HOT 4
- http/request header issue HOT 2
- Help w/ Functional Wrapping HOT 5
- missing Match function on Either type HOT 2
- Dependency Dashboard
- onleft error return nil panics HOT 2
- Is there any `next`, `any` function similar to python? HOT 6
- fp-ts bind HOT 3
- ReaderIO / ReaderIOEither dependency injection sample HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fp-go.