Is there already or can I declare a more pipe friendly upcast?
up vote
6
down vote
favorite
I want to be able to just
let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast
However, that then constrains 'T
to be 'TResult
instead of it being something that can be cast to 'TResult
I know I can
|> fun x -> x :> 'TResult
|> fun x -> upcast x
|> fun x -> x :> _
but then if I'm doing anything else on that line I have to go back and put ()
around the fun x -> upcast x
or it thinks what I'm doing is part of the fun x
function.
can I define or does there exist a way to be able to
|> upcast |>
doesn't work
|> ( ( :> ) 'TResult)
doesn't work and is messy
edit
In response to Thomas Petricek - minimal failing auto-upcast sample:
module Test =
let inline f'<'t>():IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> fun x -> x :> IReadOnlyCollection<_>
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
f#
add a comment |
up vote
6
down vote
favorite
I want to be able to just
let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast
However, that then constrains 'T
to be 'TResult
instead of it being something that can be cast to 'TResult
I know I can
|> fun x -> x :> 'TResult
|> fun x -> upcast x
|> fun x -> x :> _
but then if I'm doing anything else on that line I have to go back and put ()
around the fun x -> upcast x
or it thinks what I'm doing is part of the fun x
function.
can I define or does there exist a way to be able to
|> upcast |>
doesn't work
|> ( ( :> ) 'TResult)
doesn't work and is messy
edit
In response to Thomas Petricek - minimal failing auto-upcast sample:
module Test =
let inline f'<'t>():IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> fun x -> x :> IReadOnlyCollection<_>
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
f#
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53
add a comment |
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I want to be able to just
let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast
However, that then constrains 'T
to be 'TResult
instead of it being something that can be cast to 'TResult
I know I can
|> fun x -> x :> 'TResult
|> fun x -> upcast x
|> fun x -> x :> _
but then if I'm doing anything else on that line I have to go back and put ()
around the fun x -> upcast x
or it thinks what I'm doing is part of the fun x
function.
can I define or does there exist a way to be able to
|> upcast |>
doesn't work
|> ( ( :> ) 'TResult)
doesn't work and is messy
edit
In response to Thomas Petricek - minimal failing auto-upcast sample:
module Test =
let inline f'<'t>():IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> fun x -> x :> IReadOnlyCollection<_>
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
f#
I want to be able to just
let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast
However, that then constrains 'T
to be 'TResult
instead of it being something that can be cast to 'TResult
I know I can
|> fun x -> x :> 'TResult
|> fun x -> upcast x
|> fun x -> x :> _
but then if I'm doing anything else on that line I have to go back and put ()
around the fun x -> upcast x
or it thinks what I'm doing is part of the fun x
function.
can I define or does there exist a way to be able to
|> upcast |>
doesn't work
|> ( ( :> ) 'TResult)
doesn't work and is messy
edit
In response to Thomas Petricek - minimal failing auto-upcast sample:
module Test =
let inline f'<'t>():IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> fun x -> x :> IReadOnlyCollection<_>
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
f#
f#
edited Nov 9 at 16:45
asked Nov 8 at 18:39
Maslow
12.5k1482167
12.5k1482167
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53
add a comment |
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53
add a comment |
2 Answers
2
active
oldest
votes
up vote
5
down vote
As far as I know, specifying the kind of constraint between 'T
and 'TResult
is not possible. There is a related question about this with links to more information and a feature request.
That said, I wonder why do you need this? The F# compiler is able to insert upcasts automatically, even when using pipes, so if you want to do this as part of a longer pipe, it should not be needed. Here is a simple illustration:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
I guess you might need pipe-able upcast if you wanted to have it at the end of the pipeline, but then I'd just do the upcast on a separate line. Or is your question motivated by some more complicated cases where the implicit upcast does not work?
EDIT 1: Here is a minimal example using ReadOnlyCollection
and IReadOnlyList
which works:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
EDIT 2: To comment on the update - the problem here is that automatic upcasts are only inserted when passing arguments to functions, but in the second example, the type mismatch is between the result of the pipe and the return type of the function. You can get that to work by adding an identity function of type IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>
to the end of the pipe:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
This works, because now the upcast is inserted automatically when passing the argument to the id
function - and this then returns a type that matches with the return type of the function.
Yeah auto upcast fromReadOnlyCollection<_>
toIReadOnlyList<_>
doesn't seem to work
– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
add a comment |
up vote
0
down vote
much simpler and unexpected
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
As far as I know, specifying the kind of constraint between 'T
and 'TResult
is not possible. There is a related question about this with links to more information and a feature request.
That said, I wonder why do you need this? The F# compiler is able to insert upcasts automatically, even when using pipes, so if you want to do this as part of a longer pipe, it should not be needed. Here is a simple illustration:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
I guess you might need pipe-able upcast if you wanted to have it at the end of the pipeline, but then I'd just do the upcast on a separate line. Or is your question motivated by some more complicated cases where the implicit upcast does not work?
EDIT 1: Here is a minimal example using ReadOnlyCollection
and IReadOnlyList
which works:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
EDIT 2: To comment on the update - the problem here is that automatic upcasts are only inserted when passing arguments to functions, but in the second example, the type mismatch is between the result of the pipe and the return type of the function. You can get that to work by adding an identity function of type IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>
to the end of the pipe:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
This works, because now the upcast is inserted automatically when passing the argument to the id
function - and this then returns a type that matches with the return type of the function.
Yeah auto upcast fromReadOnlyCollection<_>
toIReadOnlyList<_>
doesn't seem to work
– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
add a comment |
up vote
5
down vote
As far as I know, specifying the kind of constraint between 'T
and 'TResult
is not possible. There is a related question about this with links to more information and a feature request.
That said, I wonder why do you need this? The F# compiler is able to insert upcasts automatically, even when using pipes, so if you want to do this as part of a longer pipe, it should not be needed. Here is a simple illustration:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
I guess you might need pipe-able upcast if you wanted to have it at the end of the pipeline, but then I'd just do the upcast on a separate line. Or is your question motivated by some more complicated cases where the implicit upcast does not work?
EDIT 1: Here is a minimal example using ReadOnlyCollection
and IReadOnlyList
which works:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
EDIT 2: To comment on the update - the problem here is that automatic upcasts are only inserted when passing arguments to functions, but in the second example, the type mismatch is between the result of the pipe and the return type of the function. You can get that to work by adding an identity function of type IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>
to the end of the pipe:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
This works, because now the upcast is inserted automatically when passing the argument to the id
function - and this then returns a type that matches with the return type of the function.
Yeah auto upcast fromReadOnlyCollection<_>
toIReadOnlyList<_>
doesn't seem to work
– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
add a comment |
up vote
5
down vote
up vote
5
down vote
As far as I know, specifying the kind of constraint between 'T
and 'TResult
is not possible. There is a related question about this with links to more information and a feature request.
That said, I wonder why do you need this? The F# compiler is able to insert upcasts automatically, even when using pipes, so if you want to do this as part of a longer pipe, it should not be needed. Here is a simple illustration:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
I guess you might need pipe-able upcast if you wanted to have it at the end of the pipeline, but then I'd just do the upcast on a separate line. Or is your question motivated by some more complicated cases where the implicit upcast does not work?
EDIT 1: Here is a minimal example using ReadOnlyCollection
and IReadOnlyList
which works:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
EDIT 2: To comment on the update - the problem here is that automatic upcasts are only inserted when passing arguments to functions, but in the second example, the type mismatch is between the result of the pipe and the return type of the function. You can get that to work by adding an identity function of type IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>
to the end of the pipe:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
This works, because now the upcast is inserted automatically when passing the argument to the id
function - and this then returns a type that matches with the return type of the function.
As far as I know, specifying the kind of constraint between 'T
and 'TResult
is not possible. There is a related question about this with links to more information and a feature request.
That said, I wonder why do you need this? The F# compiler is able to insert upcasts automatically, even when using pipes, so if you want to do this as part of a longer pipe, it should not be needed. Here is a simple illustration:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
I guess you might need pipe-able upcast if you wanted to have it at the end of the pipeline, but then I'd just do the upcast on a separate line. Or is your question motivated by some more complicated cases where the implicit upcast does not work?
EDIT 1: Here is a minimal example using ReadOnlyCollection
and IReadOnlyList
which works:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
EDIT 2: To comment on the update - the problem here is that automatic upcasts are only inserted when passing arguments to functions, but in the second example, the type mismatch is between the result of the pipe and the return type of the function. You can get that to work by adding an identity function of type IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>
to the end of the pipe:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
This works, because now the upcast is inserted automatically when passing the argument to the id
function - and this then returns a type that matches with the return type of the function.
edited Nov 10 at 23:43
answered Nov 8 at 21:28
Tomas Petricek
196k13285458
196k13285458
Yeah auto upcast fromReadOnlyCollection<_>
toIReadOnlyList<_>
doesn't seem to work
– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
add a comment |
Yeah auto upcast fromReadOnlyCollection<_>
toIReadOnlyList<_>
doesn't seem to work
– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
Yeah auto upcast from
ReadOnlyCollection<_>
to IReadOnlyList<_>
doesn't seem to work– Maslow
Nov 9 at 4:56
Yeah auto upcast from
ReadOnlyCollection<_>
to IReadOnlyList<_>
doesn't seem to work– Maslow
Nov 9 at 4:56
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
@Maslow My trivial test (see edit) worked - it would be interesting to see a small counter-example for this - I suspect there is one, because the auto-upcasts are not perfect, but I'm not sure what exactly it needs to look like...
– Tomas Petricek
Nov 9 at 14:51
edited to add the sample
– Maslow
Nov 9 at 16:46
edited to add the sample
– Maslow
Nov 9 at 16:46
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
dammit, I was in an edit frenzy on the question and edited your answer on accident, and I'm not sure I can undo that
– Maslow
Nov 9 at 16:50
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
@Maslow Thanks for the example! This is actually a bit different situation - see my Edit 2!
– Tomas Petricek
Nov 10 at 23:43
add a comment |
up vote
0
down vote
much simpler and unexpected
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
add a comment |
up vote
0
down vote
much simpler and unexpected
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
add a comment |
up vote
0
down vote
up vote
0
down vote
much simpler and unexpected
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
much simpler and unexpected
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
answered Nov 12 at 1:12
Maslow
12.5k1482167
12.5k1482167
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%2f53214150%2fis-there-already-or-can-i-declare-a-more-pipe-friendly-upcast%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
in the edit, the 2nd example fails, while the first works
– Maslow
Nov 9 at 16:53