Suppose I have an application whose core data are Projects, Document Sets ("DocSets"), and Documents ("Docs"). Docs are not restricted to any particular content-type; they could be spreadsheets, images, HTML, etc., and can have functions/behaviors other documents don't have. Similarly, I might have multiple kinds of DocSets depending on the type of behavior I need. Maybe this DocSet presents the documents in a flat list, maybe that one associates a status with each document, and has some cool rendering trick based off of status.
The code might look like this if I wasn't using typeclasses:
data Project = Project {
projName :: Text,
projDocSets :: [DocSet]
}
data DocSet = DocSet {
dsName :: Text,
dsDocs :: [Doc]
}
data Doc = Doc {
docTitle :: Text,
docType :: Text,
docContents :: ByteString
}
The problem I see with this is while it allows there to be multiple kinds of Docs (via the docType field), it essentially uses manual type checking, which doesn't feel right (in my head). I could have data constructors for PagedTextDoc, ContinuousTextDoc, SpreadsheetDoc, ImageDoc, etc. That seems like poor modularity to me.
EDIT: My "poor modularity" comment relies on knowledge that wasn't communicated very well. Each Doc has some common behaviors
((de-)serialization, being grouped into a DocSet, a title, rendering,
others as the application evolves), and some unique behaviors
(internal representation in an easy-to-edit format, saving incremental
edits, partial rendering to HTML assuming application is a web app).
Even if that weren't the case, it seems to me like the app would be
more modular if I could just create a new module, define my document
and what you can do with it, and bang, document is now supported. That
way, I define my paginated document over here, my spreadsheet over
there, and the two don't care about each other at all.
Maybe I could use a typeclass for Docs?
data DocSet = DocSet {
dsName :: Text,
dsDocs :: [Doc]
}
class Doc d where
docTitle :: d -> Text
docType :: d -> Text
docContents :: d -> ByteString
The declaration for dsDocs now doesn't typecheck; lists only work for one particular concrete type, vs. any member of a typeclass. The DocSet definitely needs to be able to store/reference multiple kinds of documents.
I've tried to do some searching, but frankly, my Google skills completely fail here. Am I thinking about the data structures correctly? Is the approach with all of (Proj, DocSet, Doc) as a single data constructor each really the best way of handling this, or am I missing something about the way Haskell handles polymorphism?
Well, the class-based proposal doesn't even work. Classes aren't types. You can't have [Doc] if Doc is a class.
The usual approach here is to determine what it is you're modeling, exactly.
Do you want a bunch of things that behave uniformly, and can easily be packaged up together? Then put that behavior into a type. This is usually done by creating a record that holds a function for each kind of behavior you want.
On the other hand, do you have a bunch of things that require very different handling? In that case, put the data into a bunch of types and let the type checker (and exhaustiveness checker) guide you along the way to make sure you're always handling the right thing in the right place.
I don't recommend using classes for this at all. Classes are (mostly) good only for the situation where you can write type-polymorphic code that is meaningful when there is a concrete type, but you don't need to know what the type is. (This is a slight exaggeration, but it's close enough to the truth to use it as a first-approximation heuristic.)
Suppose I have an application whose core data are Projects, Document
Sets ("DocSets"), and Documents ("Docs"). Docs are not restricted to
any particular content-type; they could be spreadsheets, images, HTML,
etc., and can have functions/behaviors other documents don't have.
It sounds like you don't know that types can have multiple constructors (sum types). Instead of your Doc do:
data Doc = PagedTextDoc {docTitle :: Text, docContents :: ByteString}
| SpreadsheetDoc {docTitle :: Text, docContents :: ByteString}
... etc
Similarly, I might have multiple kinds of DocSets depending on the
type of behavior I need. Maybe this DocSet presents the documents in a
flat list, maybe that one associates a status with each document, and
has some cool rendering trick based off of status.
data DocSet = ListDocset Text [Doc] | KoolDocset [(Status, Doc)] | ...etc
Related
I have defined a generic interface using Enterprise Architect (see figure below).
I would now like to specify the following realization:
class AircraftsTypesRepository implements Repository<AircraftTypes, Integer>
Is there a way for EA to automatically bind types and method signatures to the generic types I specified in the base interface. In other words, I would like to show in the diagram that for the AircraftTypesRepository class, T and K and bound to T=AircraftTypes, and K=Integer. I would also like to see this reflected in the interface methods
I thought about this and (as there's no native support) would suggest to script that. There are plenty of ways, so I'd take a KISS one. The Realize relation could be adorned with tagged values named Bind<val> or so where <val> is the name of a template parameter (in your example T or K). These TVs should then be defined as RefGUID which allows them to link to an EA element. Creating these TVs should be one script which looks into the templated class. You find the template definition in the table t_xref with
SELECT description FROM t_xref
WHERE client = `<GUID of element>` AND type = `elment property`
This will contain something like
#ELEMENT;GUID={5EC3D8DF-BC37-4529-8F36-0D9BA363955D};Name=E;Type=ClassifierTemplateParameter;Pos=0;#ENDELEMENT;;
(I created an example with just T but you will decode it easily, I guess.)
Now that you have the tagged value(s) set in the Realize you can run a second script to synch the definition ("just" look for textually identical types). Later you could alter the TVs and re-synch again (AFAIK there's not hook for TVs being altered so that needs to be triggered manually).
This is not a complete solution but just a suggestion which leaves open quite some field for experimentation (and failure).
Usually, use sum types is pretty straightforward and works very well in many cases
data LifeForm = Grass | Sheep | Wolf
but when I want open my "LifeForm" on my problems I fall in heterogeneus containers, Data.Dynamic, Data.Typeable and so on (here a silly example using a simple String to discover the "type" at runtime).
I'll like extend my "LifeForm" in a manner that new "life forms" can interact and restrict between them with their own and new properties (classes).
Typically downcast at runtime is the simplest way in many languages.
I'm looking for useful strategies I could use to extend (without change the "core") containers when their elements may know or not optional properties of the others (eg. class Vegetable a, class Runner a, ...).
How do you deal with it?
Are Data.MultiConstrainedDynamic and others the best way?
Is preferable try to avoid this extensibility?
Thk!
UPDATED to clarify "What's not clear at all is what you wish you could do with it. "
Once I've my "lifeforms core":
I like add the "wind" defining a new class AffectedByTheWind a, now any lifeform could be affected by the wind (for every "world step" the "Wind life form" will check all AffectedByTheWind).
I like add the Dodo bird instancing class Fly a, class IsMeat a, class Might a, ... and automatically other "life forms" can interact with it.
I like add a "watcher life form" (a "spirit form") reporting how many life forms can run (instance class Runner a).
I like add a "behavior life form" (a "element form") that check how many IsMeat forms exists and reduce their vital energy.
...
All of this can be achieved using sum types or fixed type class hierarchy but is not extensible in the "expression problem" sense.
I use WSCF blue to generate web service code from wsdl. Sometimes choice-element in xsd is generated to Item and ItemElementName. Sometimes just Item. Couldn't find any logic in this.
The answer it that there must be choice-elements of same type in schema. E.g. 2 int choices or 2 string choices so it can't be known anymore only by type. In my example had three different types in choice -> no ItemElementName enumeration and property.
In a JSF page I have to display the data from an entity.
This entity has some int fields which cannot be displayed directly but need to be translated into a descriptive string.
Between them some can have a limited number of values, others have lots of possible values (such as a wordlwide Country_ID) and deserve a table on the Db with the association (ID, description).
This latter case can easily be solved navigating via relationship from the original entity to the entity corresponding to the dictionary table (ID, description) but I don't want to introduce new entities just to solve translations form ID to description.
Besides another integer field has special needs: the hundred thousand number should be changed with a letter according to a rule such as 100015 -> A00015, 301023 -> C01023.
Initially I put the translation code inside the entity itself but I know the great limits and drawbacks of this solution.
Then I created a singletone (EntityTranslator) with all the methods to translate the different fields. For cases where the field values are a lot I put them inside a table which is loaded from the singletone and transformed in a TreeMap, otherwise the descriptions are in arrays inside the class.
In the ManagedBean I wrote a getter for EntityTranslator and inside the jsf I use quite long el statements like the following:
#{myManagedBean.entityTranslator.translateCountryID(myManagedBean.selectedEntity.countryID)}
I think the problem is quite general and I'm looking for a standard way to solve it but, as already stated, I don't want to create new 'stupid' entities only to associate an ID to a description, I think it is overkill.
Another possibility is the use of converters Object(Integer) <-> String but I'm more comfortable in having all the translation needs for an Entity inside the same class.
Your question boils down to the following simple line:
How can I display a field different from id of my entity in my view and how can I morph an integer field into something more meaningful.
The answer is that it depends on a situation.
If you solely want to input/output data, you don't need id at all apart from the possible view parameter like ?id=12345. In this case you can input/output anything you want in your view: the id is always there.
If you want to create a new entity most possibly you have a way of generating ids via JPA, or database, or elsehow besides the direct input from the user. In this situation you don't need to mess with ids as well.
If you want to use information on other entities like show user a dropdown box with e.g. a list of countries, you always have the option to separate label (let it be name) and value (let it be id), or even have a unique not null column containing the country name in your database table that will serve as a natural identifier. If you'd like to get data from the user using an input text field you always can create a converter that will do the job of transforming user input strings to actual entity objects.
Regarding the transformation of your integers, you've actually got several choices: the first one is to attach a converter for these fields that will roughly do 301023 -> C01023 and C01023 -> 301023 transformations, the second one is to write a custom EL function and the third one is to prepare the right model beforehand / do the transformations on-the-fly.
I'm in the middle of trying to copy a custom content type from one web to another. I've googled around and found some examples that use FieldLinks and Fields. I'm kind of lost as to which one to use, since when I get the FieldLinks from my source web, I get 3 fields; while retrieving from Fields only returned me 2 fields... the custom field is missing. I'm pretty darn sure that I've added the fields at the proper level since I did it via the interface. But when retrieving it using code... the numbers just don't add up.
So besides from that strange problem, I want to know what is the difference between FieldLinks and Fields, and when dealing with them in Content Types (programmatically) which one should I use?
Thanks.
SPFields are fields themselves, while SPFieldLinks are references to the fields. This is a good read that will explain things in detail. In general practice, it is safer to use SPFieldLinks when you are working on the actual content type definition. However, I'll give a quick summary here.
Lists and Webs contain the actual fields with field data. A content type, on the other hand, only holds Field Reference, which simply points at the corresponding field in the list or web. This gets a bit confusing, because content types have both an SPFieldLinkCollection and an SPFieldCollection.
The SPFieldLinkCollection is used in the actual definition of the content type, and is what you would want to use in your situation of copying a content type from one web to another. SPFieldLinks correspond to the actual elements in the XML Schema for a content type.
Comparatively, when you call on a content type's SPFieldCollection and retrieve a Field from it, what is actually happening is that the content type is checking the corresponding field reference, and then looking up in the list/web to get the actual field. Basically, think of the SPFieldCollection in the same way a lookup works: it is worthless without both the lookup value and the lookup source.