Last active
November 8, 2020 21:18
-
-
Save isaacabraham/a184e2a3f97f607ca965e7a71abb64dd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Couple of interfaces | |
| type IFoo = interface end | |
| type IBar = interface end | |
| // Some records that implement the interfaces | |
| type FooImpl1 = { Name : string } interface IFoo | |
| type FooImpl2 = { OtherName : string } interface IFoo | |
| type BarImpl1 = { Age : int } interface IBar | |
| // Some example lists of data | |
| let listOfFooImpl1s = [ { Name = "Isaac" }; { Name = "Blah" } ] | |
| let listOfFoos1 : IFoo list = [ { Name = "Isaac" }; { Name = "Blah" } ] // Works | |
| let listOfFoos2 : IFoo list = [ { Name = "Isaac" }; { OtherName = "Blah" } ] // Even this works | |
| let listOfBars : IBar list = [ { Age = 21 } ] | |
| let listOfFoosBad1 = [ { Name = "Isaac" } :> IFoo; { OtherName = "Blah" } ] // This doesn't work | |
| let listOfFoosBad2 = [ { Name = "Isaac" } :> IFoo; { OtherName = "Blah" } :> _ ] // This works but is too verbose | |
| let listOfFoosBad3 : IFoo list = [ "Isaac"; "Blah" ] |> List.map(fun x -> { Name = x }) // This doesn't work! | |
| // A class that "consumes" IFoos and IBars | |
| type Runner = | |
| static member Go(foo:IFoo) = printfn "A foo!" | |
| static member Go(foo:IFoo list) = printfn "A list of foo!" | |
| static member Go(foo:IBar) = printfn "A bar!" | |
| static member Go(foo:IBar list) = printfn "A list of bar!" | |
| Runner.Go listOfFoos1 | |
| Runner.Go listOfFoos2 | |
| Runner.Go listOfBars | |
| Runner.Go listOfFooImpl1s // This doesn't work. I want this to automatically resolve to IFoo list. | |
| // A class that implements the IFoo version as a flexible type. | |
| type SmartRunner = | |
| static member Go(foo:IFoo) = printfn "A foo!" | |
| static member Go(foo:#IFoo list) = printfn "A list of foo!" | |
| static member Go(foo:IBar) = printfn "A bar!" | |
| static member Go(foo:IBar list) = printfn "A list of bar!" | |
| SmartRunner.Go listOfFoos1 | |
| SmartRunner.Go listOfFoos2 | |
| SmartRunner.Go listOfBars | |
| SmartRunner.Go listOfFooImpl1s // Works! However, the signature of that Go method has now changed to be "any 'a that implements IFoo as a constraint". The constraint is also not shown in all tooling, reducing readability. | |
| SmartRunner.Go [ { Name = "Isaac" }; { OtherName = "Blah" } ] // This unfortunately doesn't work | |
| // However, what if we want to also make the IBar list version flexible? | |
| type SmarterRunner = | |
| static member Go(foo:IFoo) = printfn "A foo!" | |
| static member Go(foo:#IFoo list) = printfn "A list of foo!" | |
| static member Go(foo:IBar) = printfn "A bar!" | |
| static member Go(foo:#IBar list) = printfn "A list of bar!" // doesn't compile - the second overload and this one have the same signature. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment