4 ms·
Am I missing something? This appears to be just outsourcing the record schema definition to a sample object in another file. You still have to keep that sampl
by blunte 7y ago
Am I missing something? This appears to be just outsourcing the record schema definition to a sample object in another file.
You still have to keep that sample updated to handle new runtime data.
- rsstack 7y agoThat other file can be an online API spec, a database instance, etc. Anything that can be accessed programmatically.
- whb07 7y agoIt keeps a structure and defines the types for you to some extent. But obviously if there are breaking changes just like with anything else....things break.
- kroltan 7y agoYes, but it is comparatively easier getting say, the result of an API's GET and pasting into a file as a sample, than manually tweaking types. At least when you're starting out or if it's a small F# program. You could even use the actual network path, but that's a bit... wilder in terms of maintenance/reproducibility. Plus, since you can have arbitrary providers, such as a provider that connects to a DB and generates a type-safe "ORM" over your relational database[0] with no configuration other than pointing to the data source you're going to access at runtime. Perfect if you want to write little data transformation scripts. [0]: http://fsprojects.github.io/SQLProvider/ http://fsprojects.github.io/SQLProvider/
- DaiPlusPlus 7y agoI don’t trust an ORM to automatically reverse a database (or generate a database from POCO types) without at least some configuration - otherwise it can not determine (for example) if two tables, where one’s schema is a subset of another, are meant to be subclasses or not. But anyway - this system feels like when we use T4 to generate types as part of the build process, but more tightly integrated. I wonder if the same could be done for C# using a Roslyn add-in.
- xixixao 7y agoIt might be easier, but it's trivial to come up with cases where you cannot generate an example that completely satisfies given JSON schema. It feels like this only works for some specific rigid JSON protocols. You also cannot restrict the types to anything more specific than JSON primitive types. A "better", certainly more common solution is to generate the type based on whatever source code is generating the JSON, if you have access to it (or have the API provided generate the signature for you).
- adgasf 7y agoYou can write a type provider that takes a schema instead of example data.
- kroltan 7y agoI'm still learning, but from what I gather, there's a) less of a need to deserialize things into specific concrete classes in functional languages b) it seems to be idiomatic to convert data yourself if you need custom conversions, rather than relying on a library to automagically deduce it. this is helped by how simple doing the manual conversion ends up being in practice.
- keithnz 7y agothe part you may be missing is this is dynamic while you are coding, so you get autocompletion of dynamic data sources ( or during an interactive session, which gives a dynamic language kind of experience, but with types)
- rubyn00bie 7y agoI guess this just seems pretty run of the mill (to me) for most statically typed languages. You import package "X" it does some meta-magic... et, voila! You get "dynamic" types because it does some fast compilation on the meta data it has and generates the method signatures, classes, et. al for you. Honestly, I feel like this should be super cool and I'm just super missing something... but I don't know what right now. Could you explain the interactive session part more?
- virtualwhys 7y agoEverything happens at compile time, no runtime reflection, on whatever schema you throw at it (json, sql, etc.), with instantaneous IDE code completion -- it's totally amazing. Not aware of any mainstream language that provides similar functionality.
- phillipcarter 7y ago> This appears to be just outsourcing the record schema definition to a sample object in another file. Not quite. There's an interface called IProvidedTypes that a component - a Type Provider - is responsible for conforming to. That component reads data of some kind and produces information in that interface. The F# compiler then takes that data and includes it in the set of symbols that it calculates for everything else in your codebase. The end result is that you get typed access to data with zero configuration aside from adding a package, and because this data is exposed to tooling, you get IntelliSense for it in your editor as the blog post shows. The paper about the subject is here: http://tomasp.net/academic/papers/fsharp-data/fsharp-data.pdf http://tomasp.net/academic/papers/fsharp-data/fsharp-data.pd... > You still have to keep that sample updated to handle new runtime data. This is only if you're working with a sample. In most cases, developers just point it at the real data source and program against that - the target URL for a JSON payload, the connection string to the SQL database, etc. There's still issues that can arise, such as a poorly-written Type Provider, but the most popular ones are well-written and won't do silly things like slurp in your whole database into memory.