Closed haf closed 9 years ago
This, sadly, is a limitation of the static type inference mechanism. Extending types in other assemblies doesn't work (here or in other libs approaches). It's annoying! I tend to find it's not a huge pain and I either provide the serialisation in my libs and don't worry about it, or occasionally end up with, essentially, serialisable DTOs (which always feels a bit superfluous).
It's an annoyance, and I'd love to come up with a way round it, but short of some fairly major compiler changes I don't think it's possible.
I'm having trouble even type-extending in the same assembly; from a different module... The thing is that I need to perform a lookup, so I can't put the static method on the actual type -- the module that handles the lookup is further down.
Hmmm. Strange, the type inference does cause some issues in some cases. I'm not sure how much of a compiler change it would need to fix! I remember getting a good explanation of the limitations from Mauricio Scheffer when discussing Fleece, but can't find it now...
On 20 April 2015 at 22:20, Henrik Feldt notifications@github.com wrote:
I'm having trouble even type-extending in the same assembly; from a different module... The thing is that I need to perform a lookup, so I can't put the static method on the actual type -- the module that handles the lookup is further down. [image: screen shot 2015-04-20 at 23 20 23] https://cloud.githubusercontent.com/assets/193115/7240769/d5d0ee48-e7b3-11e4-9130-845c1cdc8bf3.png
— Reply to this email directly or view it on GitHub https://github.com/xyncro/chiron/issues/16#issuecomment-94571950.
Playing with this, yes, it's a bit of a limitation of static type inference. You might be able to work around it in some cases though where you have to extend the types outside of a valid scope. This is ugly, but might provide a pointer to something nicer...
open Aether
open Aether.Operators
open Chiron
open Chiron.Operators
let toJson f =
snd (f (Json.Object Map.empty))
module Types =
type One =
{ Value: string }
type Two =
{ Prop: string
One: One }
module Extend =
open Types
let lens =
idLens <-?> Json.ObjectPIso >??> mapPLens "one"
type One with
static member ToJson (x: One) =
Json.write "value" x.Value
type Two with
static member ToJson (x: Two) =
Json.write "prop" x.Prop
*> Json.setLensPartial lens (toJson (One.ToJson x.One))
open Types
open Extend
[<EntryPoint>]
let main _ =
let two =
{ Prop = "Hello"
One = { Value = "World" } }
let json = toJson (Two.ToJson two)
0
For future visitors: so my conclusion is that; for type extensions to be compiled into the same type, you can't have them in different modules -- which -- taken together with the module-only-once restriction of F# -- means you probably have to collapse a lot of your code into the same module, rather than splitting it up by files. By putting the type extensions next to the types themselves, they get compiled into the proper/real type by the compiler, and consumers of the lib can use them.
Is it possible to extend the serialisation functions from another assembly? I'm trying to, but it seems the compiler isn't finding the static methods/functions.