Unify record types with overlapping fields - purescript

I have the following code:
workWithImportantField :: forall fields. { importantField :: Int | fields } -> Input
workWithImportantField = ...
workWithImportantField $
maybe { importantField: 1 } identity (Just { importantField: 1, fieldIDontCareAbout: "whatever" })
This doesn't compile because the first record doesn't have the fieldIDontCareAbout. However, I'm perfectly fine if it unifies into forall fields. { importantField :: Int | fields } so it gets passed into workWithImportantField. How would I go about doing that?
I've tried adding type annotations to various places (first record, second record, the whole expression) without success. I can always replace identity with unsafeCoerce, but I would like a type-safe solution. I can also manually pick out the fields I need by replacing identity with \{ importantField } -> { importantField }, but that doesn't look nice.

Replacing identity with pick found at Record.Extra "throws away" fieldIDontCareAbout from the second record so the types unify.

Related

Rescript Record: Key as Array

In Rescript, one can define a Record in this format:
type record1 = {
a : String
}
but NOT:
type record2 = {
[a] : String
}
I am looking to write a record that compiles to JS like:
{
[Op.or]: [12,13]
}
The use case above comes from Sequelize, and the reference is here.
My current solution:
%raw(`{[Op.or]:[12,13]}`)
It's not entirely clear how you intend to interface with the Op construct, whether you can bind to it or not, but here's an example that does, and along with Js.Dict.t effectively produces the same output:
module Op = {
#val external or: string = "Op.or"
}
Js.Dict.fromList(list{
(Op.or, [12, 23])
})
It does not directly compile to the JS you want, however, which might be a problem if you rely on something that actually parses the source code. But short of that, I believe this should do what you ask for.

Idiomatic way to handle JPA criteria ordering in Kotlin

I have a CriteriaBuilder-based query that can be ordered by several different properties.
Currently it's being handled somehow like this:
when(filters.sortBy) {
"foo" -> query.orderBy(if(isAsc) cb.asc("bar") else cb.desc("bar"))
"baz" -> query.orderBy(if(isAsc) cb.asc("quux") else cb.desc("quux"))
}
It's definitely not the most readable or maintainable code I've ever written.
Is there a better and possibly more idiomatic way to do this in Kotlin, given that it doesn't have the ternary ? : operator?
Note that some of the properties I need to order by may be subproperties of the root object, so just extracting this to a method that takes a string as the name of the order clause may not be easy.
when is an expression, so you can use it's result directly as an argument in query.orderBy()
Also, local function would help to eliminate if-else duplication part
fun query(...) {
...
fun sort(name: String) = if (isAsc) cb.asc(name) else cb.desc(name)
query.orderBy(sort(
when (filters.sortBy) {
"foo" -> "bar"
"baz" -> "quux"
}
))
...
}

Yang Model recursive search for must condition

I have a problem with a restriction on my CLI. I've been investigating yang RFC7950 (https://www.rfc-editor.org/rfc/rfc7950) but I've found nothing.
Here is an example.
grouping httpGroup {
list http-list{
key "value";
leaf value {
status current { yexte:preliminary; }
description "value to match";
must "(not(../protocol)) and (not(../network-port)))" {
error-message "Not compatible with protocol or non-TCP ports";
}
type string { length "1..255"; }
}
}
}
This group will be included in several groups with the following structure:
list and {
leaf-list protocol { ..... }
uses A;
list or {
leaf-list protocol { ..... }
uses A;
}
}
grouping A {
status{}
leaf-list protocol { ..... }
leaf-list X { ..... }
uses httpGroup;
}
I need this must condition included in httpGroup to verify that protocol value has not been configured in any level of the hierarchy.
I've made this be adding more relatives paths to search for this node:
// same level
not(../protocol)
// next level
not(../and/protocol)
not(../or/protocol)
// previous level
not(../../protocol)
not(../../protocol)
//recursively down previous level
not(../../and/protocol)
not(../../or/protocol)
// third level
not(../and/or/protocol)
not(../and/and/protocol)
As you can see, this is not a clean solution at all.
Is there any way it can be done for a whole hierarchy like:
if protocol node exists and http-list exists then error.
Thank you in advance.
Groupings are meant to be reusable. It is a bad practice to attempt to create a grouping that may only be used in specific contexts. This is exactly what happens if you define an XPath expression within a grouping and this expression references nodes that are "outside" this grouping (a not yet known ancestor data node, for example, or even worse - an ancestor with a specific name).
The proper way for you to handle this situation would be to use a refine statement in each different context where this grouping is used. You target the value leaf with it, then refine it by adding a must statement, the expression of which of course depends on usage context. You do not define a must statement within grouping http-list.
Within grouping A:
grouping A {
status{}
leaf-list protocol { ..... }
leaf-list X { ..... }
uses httpGroup {refine "http-list/value" {must "not(../../protocol)";}}
}
As you can see, grouping A is now completely self-sufficient and may be used within any context - the must will not have any problems with it.

Searching for functions by type signature & return value

I was in the shower just now and I thought: it would be cool to be able to search for appropriate functions by their type and return value with a given set of appropriate arguments. Consider,
I'm writing some code in VSCode, for example, and I have a string a and an object o like { name: string }. I want to do something like, join the string and the object's name, maybe with , as a delimiter. I am in some big codebase and I have no idea if such a function exists, or what it would be called if it did. Instead of reinventing the wheel, I type
fn(a, o): string
and a dropdown menu appears with a list of every function in the codebase of the form string -> { name: string } -> string, along with the return value of that function given my particular a and o. So with a = "hello" and o = { name: "Bob" }, in the list I might see,
greet(greeting, user) -> "Hello, Bob"
and then if I clicked this, the fn I had typed above would autocomplete to greet.
I think this would greatly improve, for example, discoverability of common helpers in large codebases. You could maybe configure it with a few folders, and make sure none of those functions had side-effects.
Does this exist somewhere as a plugin? For any language, I'm not picky. I'm aware of Hoogle. This would be like, Hoogle but with return values.

#helper.repeat in PlayFramework

I don't understand how to describe #helper.repeat in play2.2.1.
#helper.form(action = routes.Application.send) {
#helper.repeat(
field = form1("input"), min = 3
) {fld =>
#helper.inputText(
field = fld, '_label ->"input"
)
}
}
It is the part fld => #helper.inputText(field = fld) that I can't understand.
What does it mean?
I know Java, so I assume it is a functional writing, but in above code, where does the variable fld come from?
And why the tip of the arrow indicates #helper.inputText(field = fld)?
why is fld the value of field in #helper.inputText?
I have googled, but I couldn't find an enough explanation for a beginner.
I am not sure of Scala's grammar.
Please explain above code for a beginner?
Original Answer
This seems to be a bit overcomplicated. There is no need to assign values by hand. Usually you would write a repeater like this:
#helper.repeat(form1("input"), min = 3) { fld =>
#helper.inputText(fld, '_label ->"input")
}
In functional programming this is a so called higher-order function. You may know other scala built in higher-order functions like map, filter or foreach. #helper.repeat is very similar to foreach. form1("input") refers to a collection of values you want to display. min = 1 tells the repeater to show at least one field. Finally within { fld => ... } you iterate over all values defined in your collection.
In other words: { fld => ... } is just an anonymous function that takes a single Field parameter (fld) and displays a text input for that specific field.
Follow Up
Ok, I'm trying to follow up your questions from the comments. Let's start by the signature of helper.repeat. There is no magic involved here, it's just a regular Scala function:
helper.repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html]
In Scala, functions can have multiple parameter lists. Here we have two. The first parameter list takes two parameters: field and min. The second parameter list takes a single function as parameter: fieldRenderer. fieldRenderer itself takes again a single parameter (fld) and returns Html.
The important thing is, you are not passing "data" but a function instead. To clear this up:
The signature fieldRenderer: (fld: Field) => Html
is equal to def fieldRenderer(fld: Field): Html
This means, you can do anything within this function, as long as it returns Html. That's exactly what happens in the example at the very top. You pass a Field and return Html. You do that by calling #helper.inputText.
Now repeat first gets a List[Field] from field you pass as first parameter. This list corresponds to the String List of your container class. Also repeat ensures there is at least one element in that list. This is, because you passed 1 as min. Then the function fieldRenderer is applied to all elements in our list.
A pseudo code implementation of repeat could look like this:
def repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html] {
val list: List[Field] = field.getFields
var output: List[Html] = List()
for (i = 0; i < list.length; i++) {
val element: Field = list.get(i)
val html: Html = fieldRenderer(element)
output += html
}
return output
}