GithubHelp home page GithubHelp logo

Comments (4)

CarstenLeue avatar CarstenLeue commented on August 21, 2024 1

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 is MyType
  • T1 is int
  • F1 is func(MyType)int
  • ThingAction is func(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.

CarstenLeue avatar CarstenLeue commented on August 21, 2024 1

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 with N non-variadic arguments and adds a N+1st that represents the array(slice) of the variadic arguments
  • the set of BindNofM functions is meant to reduce the arity of a Mary function by pinning down (binding) the some of the parameters to static values
  • the composition functions PipeN and FlowN 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 and TupledN/UntupledN

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.

CarstenLeue avatar CarstenLeue commented on August 21, 2024 1

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.

a-lipson avatar a-lipson commented on August 21, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.