Typescript and concrete currying of overloded functions - how to?
up vote
0
down vote
favorite
I'm trying to write point free curried function in typescript. And doing so i do find an issue.
Typescript seems to be immediately evaluating type, and, in my understanding, do not allow very well curried function.
Let me illustrate by an example, first with non curried function
const fn = (x: number): string => null
function inline <T, U>(fn: (x: T) => U, src: T): U
function inline <T, U>(fn: (x: T) => U, src: Iterable<T>): Iterable<U>
function inline(fn: (x: any) => any, src: any): any
return null
const iarr = inline (fn, [1, 2]) // <-- string
const iset = inline (fn, new Set([1, 2])) // <-- Iterable<string>
Everything is in place and iarr
and iset
are correctly typed.
Now let's curry this function:
function pointfree <T, U>(fn: (x: T) => U): (src: T) => U
function pointfree <T, U>(fn: (x: T) => U): (src: Iterable<T>) => Iterable<U>
function pointfree(fn: (x: any) => any)
return (src: any): any => null
const curried = pointfree (fn) // <-- (src: number) => string
const parr = curried ([1, 2]) // <-- string
const pset = curried (new Set ([1, 2]))
// ^^^^^^^^^^^^^^^
// Argument of type 'Set<number>' is not assignable to parameter of
// type 'number'.
// or without caching same error
const pset = pointfree (fn) (new Set([1, 2]))
pset
is evaluated as soon as pointfree (fn)
is reached and is auto casted to the first type of the overloads which is an array of numbers, even without caching as curried
- Is they re a way to achieve what i want?
- Am i doing it wrong or typescript needs to evaluates, and cannot delay evaluation in this scenario ? (it remains a static check and do not need compilation)
- Is they're a good way of handling this situation?
It's very common in fp to need to partially apply function...
Thanks in advance
typescript
add a comment |
up vote
0
down vote
favorite
I'm trying to write point free curried function in typescript. And doing so i do find an issue.
Typescript seems to be immediately evaluating type, and, in my understanding, do not allow very well curried function.
Let me illustrate by an example, first with non curried function
const fn = (x: number): string => null
function inline <T, U>(fn: (x: T) => U, src: T): U
function inline <T, U>(fn: (x: T) => U, src: Iterable<T>): Iterable<U>
function inline(fn: (x: any) => any, src: any): any
return null
const iarr = inline (fn, [1, 2]) // <-- string
const iset = inline (fn, new Set([1, 2])) // <-- Iterable<string>
Everything is in place and iarr
and iset
are correctly typed.
Now let's curry this function:
function pointfree <T, U>(fn: (x: T) => U): (src: T) => U
function pointfree <T, U>(fn: (x: T) => U): (src: Iterable<T>) => Iterable<U>
function pointfree(fn: (x: any) => any)
return (src: any): any => null
const curried = pointfree (fn) // <-- (src: number) => string
const parr = curried ([1, 2]) // <-- string
const pset = curried (new Set ([1, 2]))
// ^^^^^^^^^^^^^^^
// Argument of type 'Set<number>' is not assignable to parameter of
// type 'number'.
// or without caching same error
const pset = pointfree (fn) (new Set([1, 2]))
pset
is evaluated as soon as pointfree (fn)
is reached and is auto casted to the first type of the overloads which is an array of numbers, even without caching as curried
- Is they re a way to achieve what i want?
- Am i doing it wrong or typescript needs to evaluates, and cannot delay evaluation in this scenario ? (it remains a static check and do not need compilation)
- Is they're a good way of handling this situation?
It's very common in fp to need to partially apply function...
Thanks in advance
typescript
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm trying to write point free curried function in typescript. And doing so i do find an issue.
Typescript seems to be immediately evaluating type, and, in my understanding, do not allow very well curried function.
Let me illustrate by an example, first with non curried function
const fn = (x: number): string => null
function inline <T, U>(fn: (x: T) => U, src: T): U
function inline <T, U>(fn: (x: T) => U, src: Iterable<T>): Iterable<U>
function inline(fn: (x: any) => any, src: any): any
return null
const iarr = inline (fn, [1, 2]) // <-- string
const iset = inline (fn, new Set([1, 2])) // <-- Iterable<string>
Everything is in place and iarr
and iset
are correctly typed.
Now let's curry this function:
function pointfree <T, U>(fn: (x: T) => U): (src: T) => U
function pointfree <T, U>(fn: (x: T) => U): (src: Iterable<T>) => Iterable<U>
function pointfree(fn: (x: any) => any)
return (src: any): any => null
const curried = pointfree (fn) // <-- (src: number) => string
const parr = curried ([1, 2]) // <-- string
const pset = curried (new Set ([1, 2]))
// ^^^^^^^^^^^^^^^
// Argument of type 'Set<number>' is not assignable to parameter of
// type 'number'.
// or without caching same error
const pset = pointfree (fn) (new Set([1, 2]))
pset
is evaluated as soon as pointfree (fn)
is reached and is auto casted to the first type of the overloads which is an array of numbers, even without caching as curried
- Is they re a way to achieve what i want?
- Am i doing it wrong or typescript needs to evaluates, and cannot delay evaluation in this scenario ? (it remains a static check and do not need compilation)
- Is they're a good way of handling this situation?
It's very common in fp to need to partially apply function...
Thanks in advance
typescript
I'm trying to write point free curried function in typescript. And doing so i do find an issue.
Typescript seems to be immediately evaluating type, and, in my understanding, do not allow very well curried function.
Let me illustrate by an example, first with non curried function
const fn = (x: number): string => null
function inline <T, U>(fn: (x: T) => U, src: T): U
function inline <T, U>(fn: (x: T) => U, src: Iterable<T>): Iterable<U>
function inline(fn: (x: any) => any, src: any): any
return null
const iarr = inline (fn, [1, 2]) // <-- string
const iset = inline (fn, new Set([1, 2])) // <-- Iterable<string>
Everything is in place and iarr
and iset
are correctly typed.
Now let's curry this function:
function pointfree <T, U>(fn: (x: T) => U): (src: T) => U
function pointfree <T, U>(fn: (x: T) => U): (src: Iterable<T>) => Iterable<U>
function pointfree(fn: (x: any) => any)
return (src: any): any => null
const curried = pointfree (fn) // <-- (src: number) => string
const parr = curried ([1, 2]) // <-- string
const pset = curried (new Set ([1, 2]))
// ^^^^^^^^^^^^^^^
// Argument of type 'Set<number>' is not assignable to parameter of
// type 'number'.
// or without caching same error
const pset = pointfree (fn) (new Set([1, 2]))
pset
is evaluated as soon as pointfree (fn)
is reached and is auto casted to the first type of the overloads which is an array of numbers, even without caching as curried
- Is they re a way to achieve what i want?
- Am i doing it wrong or typescript needs to evaluates, and cannot delay evaluation in this scenario ? (it remains a static check and do not need compilation)
- Is they're a good way of handling this situation?
It's very common in fp to need to partially apply function...
Thanks in advance
typescript
typescript
asked Nov 9 at 22:40
zedryas
116110
116110
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Overloads are useful when different parameter types should result in different return types. It's not useful to have two different overload signatures with the same parameter types. That's because, as the handbook says:
[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.
In your definition of pointfree
, the parameter lists are identical for each overload. That means the compiler will always choose the first one if it chooses one at all.
So, what's the right way to do this? I suggest having a single call signature that returns an overloaded function. Like this:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U):
(src: T): U,
(src: Iterable<T>): Iterable<U>
;
// implementation signature is the same as before
function pointfree(fn: (x: any) => any)
return (src: any): any => null
Let's use it:
const curried = pointfree(fn)
// const curried:
// (src: number): string;
// (src: Iterable<number>): Iterable<string>;
//
Now you can see that curried
is an overloaded function with two call signatures. So the following calls behave as you expect:
const parr = curried([1, 2]) // <-- string
const pset = curried(new Set([1, 2])) // <-- Iterable<string>
Okay, hope that helps. Good luck!
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Overloads are useful when different parameter types should result in different return types. It's not useful to have two different overload signatures with the same parameter types. That's because, as the handbook says:
[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.
In your definition of pointfree
, the parameter lists are identical for each overload. That means the compiler will always choose the first one if it chooses one at all.
So, what's the right way to do this? I suggest having a single call signature that returns an overloaded function. Like this:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U):
(src: T): U,
(src: Iterable<T>): Iterable<U>
;
// implementation signature is the same as before
function pointfree(fn: (x: any) => any)
return (src: any): any => null
Let's use it:
const curried = pointfree(fn)
// const curried:
// (src: number): string;
// (src: Iterable<number>): Iterable<string>;
//
Now you can see that curried
is an overloaded function with two call signatures. So the following calls behave as you expect:
const parr = curried([1, 2]) // <-- string
const pset = curried(new Set([1, 2])) // <-- Iterable<string>
Okay, hope that helps. Good luck!
add a comment |
up vote
2
down vote
accepted
Overloads are useful when different parameter types should result in different return types. It's not useful to have two different overload signatures with the same parameter types. That's because, as the handbook says:
[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.
In your definition of pointfree
, the parameter lists are identical for each overload. That means the compiler will always choose the first one if it chooses one at all.
So, what's the right way to do this? I suggest having a single call signature that returns an overloaded function. Like this:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U):
(src: T): U,
(src: Iterable<T>): Iterable<U>
;
// implementation signature is the same as before
function pointfree(fn: (x: any) => any)
return (src: any): any => null
Let's use it:
const curried = pointfree(fn)
// const curried:
// (src: number): string;
// (src: Iterable<number>): Iterable<string>;
//
Now you can see that curried
is an overloaded function with two call signatures. So the following calls behave as you expect:
const parr = curried([1, 2]) // <-- string
const pset = curried(new Set([1, 2])) // <-- Iterable<string>
Okay, hope that helps. Good luck!
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Overloads are useful when different parameter types should result in different return types. It's not useful to have two different overload signatures with the same parameter types. That's because, as the handbook says:
[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.
In your definition of pointfree
, the parameter lists are identical for each overload. That means the compiler will always choose the first one if it chooses one at all.
So, what's the right way to do this? I suggest having a single call signature that returns an overloaded function. Like this:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U):
(src: T): U,
(src: Iterable<T>): Iterable<U>
;
// implementation signature is the same as before
function pointfree(fn: (x: any) => any)
return (src: any): any => null
Let's use it:
const curried = pointfree(fn)
// const curried:
// (src: number): string;
// (src: Iterable<number>): Iterable<string>;
//
Now you can see that curried
is an overloaded function with two call signatures. So the following calls behave as you expect:
const parr = curried([1, 2]) // <-- string
const pset = curried(new Set([1, 2])) // <-- Iterable<string>
Okay, hope that helps. Good luck!
Overloads are useful when different parameter types should result in different return types. It's not useful to have two different overload signatures with the same parameter types. That's because, as the handbook says:
[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.
In your definition of pointfree
, the parameter lists are identical for each overload. That means the compiler will always choose the first one if it chooses one at all.
So, what's the right way to do this? I suggest having a single call signature that returns an overloaded function. Like this:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U):
(src: T): U,
(src: Iterable<T>): Iterable<U>
;
// implementation signature is the same as before
function pointfree(fn: (x: any) => any)
return (src: any): any => null
Let's use it:
const curried = pointfree(fn)
// const curried:
// (src: number): string;
// (src: Iterable<number>): Iterable<string>;
//
Now you can see that curried
is an overloaded function with two call signatures. So the following calls behave as you expect:
const parr = curried([1, 2]) // <-- string
const pset = curried(new Set([1, 2])) // <-- Iterable<string>
Okay, hope that helps. Good luck!
answered Nov 10 at 0:43
jcalz
20.4k21535
20.4k21535
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234178%2ftypescript-and-concrete-currying-of-overloded-functions-how-to%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown