Say i have a long data structure definition
data A = A {
x1 :: String
, x2 :: String
...
, x50 :: String
}
Now i have 3 tasks:
create a draft instance of A like A { x1 = "this is x1", ... }
create an instance of A from some other data structure
create another data instance from an instance of A
The three tasks involve the tediuous copying of the lables x1, ..., x50.
A better solution would be a generic list
[
Foo "x1" aValue1
, Foo "x2" aValue2
...
]
because it would make traversal and creating a draft much easier (the list definition is the draft already). The downside is that mapping other data structures to and from this would be more dangerous, since you lose static type checking.
Does this make sense?
Is there a generic but safe solution?
Edit: To give you a better idea, it's about mapping business data to textual representation like forms and letters. E.g.:
data TaxData = TaxData {
taxId :: String
, income :: Money
, taxPayed :: Money,
, isMarried :: Bool
...
}
data TaxFormA = TaxFormA {
taxId :: Text
, isMarried :: Text
...
}
data TaxFormB = TaxFormB {
taxId :: Text
, taxPayedRounded :: Text
...
}
Those get transformed into a stream of text, representing the actual forms. If i would create a form from tax data in one pass and next year any form field would have moved, there would e.g. be a stray "0.0" and i would not know where it belongs. That's what the intermediate datat strcuture is for: it makes it easy to create draft data.
So i need to map the actual TaxData to those intermediate form data; i need to map those form data to the actual form textual representation; i need to create draft intermediate form data. On one hand i hate repeating those data labels, on the other hand it gives me saftey, that i don't confuse any label while mapping. Is there a silver bullet?
Deeply structured data like this is most idiomatically expressed in Haskell as nested, algebraic data types, as you have done. Why? It gives the most type structure and safety to the data, preventing functions from putting the data into the wrong format. Further safety can be gained by newtyping some of the types, to increase the differences between data in each field.
However, very large ADTs like this can be unwieldy to name and manipulate. A common situation in compiler design is specifying such a large ADT, for example, and to help write the code for a compiler we tend to use a lot of generic programming tricks: SYB, meta-programming, even Template Haskell, to generate all the boilerplate we need.
So, in summary, I'd keep the ADT approach you are taking, but look at using generics (e.g. SYB or Template Haskell) to generate some of your definitions and helper functions.
Related
I'm new to Elm (version 0.19).
On thing that's bugging me is the huge list of arguments I'm passing around. I think the problem is due to my OOP way of thinking. In my code I have a bunch of helper functions that require access to my model (TEA). I have been using let / in syntax in the view function to define these helpers as this gives them access to the model argument. However I have 10+ helper functions and I'm constantly passing them around, it makes my code look ugly and hard to comprehend. In OOP these helper functions would all be methods on some object that I would pass instead.
Code snippet below is a contrived example that uses elm-ui. Full example can be run on Ellie
Element.layout []
<| column
[ w |> px |> width
, h |> px |> height
, blueBg
, centerX
, centerY
]
[ el [centerX, centerY, whiteTxt, fontSize 40] <| text "Hello world"
, header w h scale whiteTxt space blueBg pad radius whiteBg fontSize blackTxt greyBg blueTxt
]
header w h scale whiteTxt space blueBg pad radius whiteBg fontSize blackTxt greyBg blueTxt =
-- code here
el [] Element.none
Whats the best way to do this?
There are several strategies for this:
Use types to abstract away data complexity. Model your problem using types, and then create simple functions to operate on those types.
Define constants and helper functions at higher levels so that they are in scope for functions, rather than passing them in as a parameter.
Narrow down function parameters to only what is strictly needed for that function.
In the header example, you might provide your own types for the style, title and subtitle:
type alias Title = String
type alias SubTitle = String
header : HeaderStyle -> Title -> SubTitle -> Element Msg
When you do have lots of information to pass around, records are usually the first go-to for holding data. For example, if you're reusing the header function multiple times with different styling, then a HeaderStyle record type might be useful:
type alias HeaderStyle = { borderColor : Color
, textColor: Color
, backgroundColor : Color
...
}
Now since the title and subtitle are part of the header you could also pull it all into one record:
type alias HeaderData = { borderColor : Color
, textColor: Color
, backgroundColor : Color
, bannerText : String
, bannerImage : Url
, headerTitle : Title
, headerSubTitle : SubTitle
...
}
If we pay attention to the types supplied by the library, we can see that for elm-ui it might make more sense to keep the styles in a list to match their types. Modifying our record, we get:
type alias HeaderData = { styleList : List (Attribute Msg)
, headerTitle : Title
, headerSubTitle : SubTitle
...
}
The advantage here is that we can extract the style list and use it directly in a function from the Element module by calling the automatic function styleList: HeaderData -> List (Attribute Msg).
The disadvantage is that we've lost our nice compiler error message if someone makes a HeaderData missing some key styles.
Either way, now our header function is down to only one input.
header : HeaderData -> Element Msg
Great, but this still means that every time we run header we need to populate a HeaderData. How can we simplify that?
One strategy is to use constants at the top level, and use helper functions / partial application to apply these constants.
We can for example define a top level constant and helper function that lets us create various predefined headers:
pageStyle : List (Attribute Msg)
pageStyle = [ Border.color <| rgb255 35 97 146
, Font.color <| rgb255 35 97 146 ]
redHeaderStyle : Title -> HeaderData
redHeaderStyle title =
{ styleList : pageStyle
++ [ Background.color red
, Font.color black
...
]
, headerTitle : title
}
Here pageStyle can be used elsewhere, and readHeaderStyle adds to it for this specific case. Note that we've left one parameter for later, since the title may change for each application.
Of course in Elm you are not restricted to lists and records - you could also use product and sum types for Header. When to use each type is going to depend on things like where you want the type safety and how you want to compose functions.
So to summarize:
Start by modelling your problem domain using types, rather than thinking in terms of objects or components.
Don't try to make everything generic and reusable. Instead create types that hold information, and use helper functions so you only have to worry about what's relevant.
Don't be afraid of defining constants and helper functions at the top-level. Limit your use of let..in constructs to improving readability, rather than for grouping definitions as though they're methods.
Write helper functions for your types on an as-needed basis, rather than trying to create a library of every possible functionality.
If you want to compartmentalise similar functions and types, you can use modules and then import them qualified to a convenient name. This way you can say e.g. Background.color and Element.row.
Finally, Scott Wlashchin gives a good talk on design strategies in functional programming: Functional programming design patterns by Scott Wlaschin
As you can see in the title , I'd appreciate it if somebody can tell the usage of the Class .
There's a inside enum Type ,how to use it?
public static enum Type {
BETWEEN(2, "IsBetween", "Between"), IS_NOT_NULL(0, "IsNotNull", "NotNull"), IS_NULL(0, "IsNull", "Null"), LESS_THAN(
"IsLessThan", "LessThan"), LESS_THAN_EQUAL("IsLessThanEqual", "LessThanEqual"), GREATER_THAN("IsGreaterThan",
"GreaterThan"), GREATER_THAN_EQUAL("IsGreaterThanEqual", "GreaterThanEqual"), BEFORE("IsBefore", "Before"), AFTER(
"IsAfter", "After"), NOT_LIKE("IsNotLike", "NotLike"), LIKE("IsLike", "Like"), STARTING_WITH("IsStartingWith",
"StartingWith", "StartsWith"), ENDING_WITH("IsEndingWith", "EndingWith", "EndsWith"), NOT_CONTAINING(
"IsNotContaining", "NotContaining", "NotContains"), CONTAINING("IsContaining", "Containing", "Contains"), NOT_IN(
"IsNotIn", "NotIn"), IN("IsIn", "In"), NEAR("IsNear", "Near"), WITHIN("IsWithin", "Within"), REGEX(
"MatchesRegex", "Matches", "Regex"), EXISTS(0, "Exists"), TRUE(0, "IsTrue", "True"), FALSE(0, "IsFalse",
"False"), NEGATING_SIMPLE_PROPERTY("IsNot", "Not"), SIMPLE_PROPERTY("Is", "Equals");
// Need to list them again explicitly as the order is important
// (esp. for IS_NULL, IS_NOT_NULL)
private static final List<Part.Type> ALL = Arrays.asList(IS_NOT_NULL, IS_NULL, BETWEEN, LESS_THAN, LESS_THAN_EQUAL,
GREATER_THAN, GREATER_THAN_EQUAL, BEFORE, AFTER, NOT_LIKE, LIKE, STARTING_WITH, ENDING_WITH, NOT_CONTAINING,
CONTAINING, NOT_IN, IN, NEAR, WITHIN, REGEX, EXISTS, TRUE, FALSE, NEGATING_SIMPLE_PROPERTY, SIMPLE_PROPERTY);
...}
Part is internal to Spring Data. It is not intended to be used by client code. So if you don't implement your own Spring Data Modul you shouldn't use it at all nor anything inside it.
A Part is basically an element of an AST that will probably result in an element of a where clause or equivalent depending on the store in use.
E.g. if you have a method findByNameAndDobBetween(String, Date, Date) parsing the method name will result in two parts. One for the name condition and one for the DOB between condition.
The type enum lists all the different types of conditions that are possible.
The parameters of the elements are the number of method arguments required and (possibly multiple) Strings that identify this type inside a method name.
I am using GrapgQL and Java. I need to extract all the children belongs to specific parent. I have used the below way but it will fetch only the parent and it does not fetch any children.
schema {
query: Query
}
type LearningResource{
id: ID
name: String
type: String
children: [LearningResource]
}
type Query {
fetchLearningResource: LearningResource
}
#Component
public class LearningResourceDataFetcher implements DataFetcher{
#Override
public LearningResource get(DataFetchingEnvironment dataFetchingEnvironment) {
LearningResource lr3 = new LearningResource();
lr3.setId("id-03");
lr3.setName("Resource-3");
lr3.setType("Book");
LearningResource lr2 = new LearningResource();
lr2.setId("id-02");
lr2.setName("Resource-2");
lr2.setType("Paper");
LearningResource lr1 = new LearningResource();
lr1.setId("id-01");
lr1.setName("Resource-1");
lr1.setType("Paper");
List<LearningResource> learningResources = new ArrayList<>();
learningResources.add(lr2);
learningResources.add(lr3);
learningResource1.setChildren(learningResources);
return lr1;
}
}
return RuntimeWiring.newRuntimeWiring().type("Query", typeWiring -> typeWiring.dataFetcher("fetchLearningResource", learningResourceDataFetcher)).build();
My Controller endpoint
#RequestMapping(value = "/queryType", method = RequestMethod.POST)
public ResponseEntity query(#RequestBody String query) {
System.out.println(query);
ExecutionResult result = graphQL.execute(query);
System.out.println(result.getErrors());
System.out.println(result.getData().toString());
return ResponseEntity.ok(result.getData());
}
My request would be like below
{
fetchLearningResource
{
name
}
}
Can anybody please help me to sort this ?
Because I get asked this question a lot in real life, I'll answer it in detail here so people have easier time googling (and I have something to point at).
As noted in the comments, the selection for each level has to be explicit and there is no notion of an infinitely recursive query like get everything under a node to the bottom (or get all children of this parent recursively to the bottom).
The reason is mostly that allowing such queries could easily put you in a dangerous situation: a user would be able to request the entire object graph from the server in one easy go! For any non-trivial data size, this would kill the server and saturate the network in no time. Additionally, what would happen once a recursive relationship is encountered?
Still, there is a semi-controlled escape-hatch you could use here. If the scope in which you need everything is limited (and it really should be), you could map the output type of a specific query as a (complex) scalar.
In your case, this would mean mapping LearningResource as a scalar. Then, fetchLearningResource would effectively be returning a JSON blob, where the blob would happen to be all the children and their children recursively. Query resolution doesn't descent deeper once a scalar field is reached, as scalars are leaf nodes, so it can't keep resolving the children level-by-level. This means you'd have to recursively fetch everything in one go, by yourself, as GraphQL engine can't help you here. It also means sub-selections become impossible (as scalars can't have sub-selections - again, they're leaf nodes), so the client would always get all the children and all the fields from each child back. If you still need the ability to limit the selection in certain cases, you can expose 2 different queries e.g. fetchLearningResource and fetchAllLearningResources, where the former would be mapped as it is now, and the latter would return the scalar as explained.
An object scalar implementation is provided by the graphql-java ExtendedScalars project.
The schema could then look like:
schema {
query: Query
}
scalar Object
type Query {
fetchLearningResource: Object
}
And you'd use the method above to produce the scalar implementation:
RuntimeWiring.newRuntimeWiring()
.scalar(ExtendedScalars.Object) //register the scalar impl
.type("Query", typeWiring -> typeWiring.dataFetcher("fetchLearningResource", learningResourceDataFetcher)).build();
Depending on how you process the results of this query, the DataFetcher for fetchLearningResource may need to turn the resulting object into a map-of-maps (JSON-like object) before returning to the client. If you simply JSON-serialize the result anyway, you can likely skip this. Note that you're side-stepping all safety mechanisms here and must take care not to produce enormous results. By extension, if you need this in many places, you're very likely using a completely wrong technology for your problem.
I have not tested this with your code myself, so I might have skipped something important, but this should be enough to get you (or anyone googling) onto the right track (if you're sure this is the right track).
UPDATE: I've seen someone implement a custom Instrumentation that rewrites the query immediately after it's parsed, and adds all fields to the selection set if no field had already been selected, recursively. This effectively allows them to select everything implicitly.
In graphql-java v11 and prior, you could mutate the parsed query (represented by the Document class), but as of v12, it will no longer be possible, but instrumentations in turn gain the ability to replace the Document explicitly via the new instrumentDocument method.
Of course, this only makes sense if your schema is such that it can not be exploited or you fully control the client so there's no danger. You could also only do it selectively for some types, but it would be extremely confusing to use.
I am trying to migrate a library from Elm 0.15 to 0.16. The record extension mechanism has been removed.
My library offers physics calculations on bodies (represented as record), and uses record extension to allow users to add labels and other metadata about the bodies.
My example code shows this use by adding a label to all the bodies after their creation:
labeledBodies = map (\b -> { b | label = bodyLabel b.restitution b.inverseMass }) someBodies
This list of labeled bodies is also passed to the library:
main = Signal.map scene (run labeledBodies tick)
What sort of works: hardcoding a meta parameter into the Body like this:
type alias Body a = {
pos: Vec2, -- reference position (center)
velocity: Vec2, -- direction and speed
inverseMass: Float, -- we usually use only inverse mass for calculations
restitution: Float, -- bounciness factor
shape: Shape,
meta: a
}
But this makes the API more clumsy because it forces the helper functions to take an extra parameter. Is there a more elegant way to deal with this change?
What if the meta field had type Dict String String? Then you wouldn't have to do any crazy type variables clumsiness. However, you lose guarantees that all the records you pass in do indeed have labels, so you have to work with a Maybe String when you do Dict.get "label" r.meta.
What about using a tagged union type?
type BodyWithMeta =
LabeledBody Body String
labeledBodies = map (\b -> LabeledBody b (bodyLabel b.restitution b.inverseMass)) someBodies
I think I managed to fit most of the question in to the title on this one!
I'm pulling back an Object from Java in my native C++ code:
jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);
It's possible for me to check wether the return object is one of the native types using something like:
jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }
So, I now have a jobject which I know is a Boolean (note the upper case B) - The question is, what is the most efficient way (considering I already have the jobject in my native code) to convert this to a bool. Typecasting doesn't work which makes sense.
Although the above example is a Boolean I also want to convert Character->char, Short->short, Integer->int, Float->float, Double->double.
(Once i've implemented it I will post an answer to this which does Boolean.booleanValue())
You have two choices.
Option #1 is what you wrote in your self-answer: use the public method defined for each class to extract the primitive value.
Option #2 is faster but not strictly legal: access the internal field directly. For Boolean, that would be Boolean.value. For each primitive box class you have a fieldID for the "value" field, and you just read the field directly. (JNI cheerfully ignores the fact that it's declared private. You can also write to "final" fields and do other stuff that falls into the "really bad idea" category.)
The name of the "value" field is unlikely to change since that would break serialization. So officially this is not recommended, but in practice you can get away with it if you need to.
Either way, you should be caching the jmethodID / jfieldID values, not looking them up every time (the lookups are relatively expensive).
You could also use the less expensive IsSameObject function rather than IsInstanceof, because the box classes are "final". That requires making an extra GetObjectClass call to get valueObject's class, but you only have to do that once before your various comparisons.
BTW, be careful with your use of "char". In your example above you're casting the result of CallCharMethod (a 16-bit UTF-16 value) to a char (an 8-bit value). Remember, char != jchar (unless you're somehow configured for wide chars), long != jlong (unless you're compiling with 64-bit longs).
This is the solution I'm going to use if I get no more input. Hopefully it isn't this difficult but knowing JNI i'm thinking it might be:
if (env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE)
{
jmethodID booleanValueMID = env->GetMethodID(boolClass, "booleanValue", "()Z");
bool booleanValue = (bool) env->CallBooleanMethod(valueObject, booleanValueMID);
addBoolean(key, booleanValue);
}
else if(env->IsInstanceOf(valueObject, charClass) == JNI_TRUE)
{
jmethodID characterValueMID = env->GetMethodID(charClass, "charValue", "()C");
char characterValue = (char) env->CallCharMethod(valueObject, characterValueMID);
addChar (key, characterValue);
}
In general, I write jni for the better performance.
How to gain the better performance ? Using asm, primitive types and few method call.
I suggest that design your method return type can use in c/c++, such as
jint, jlong, jboolean, jbyte and jchar etc.
The redundant function call and convert will make inefficient and unmaintainable implementation.