Using a single constructor union type - elm

In Elm, I sometimes find myself defining a record type by using a union type with only a single constructor. I then use a case-statement with only a single case to unpack the record fields:
type Model =
Model { stack: List Int }
update msg model =
case model of
Model { stack } ->
...
Is there a shorter way to unpack this? The single-case case looks kind of silly. It causes unnecessary indentation and verbosity.
Also: I'm using type instead of type alias to be more explicit when dealing with the central data structures in a program (which tend to have few fields and be used in only a few places in the program, so the extra verbosity is not that much of a problem). Would it be better style to just give up on this approach and use a type alias for records whenever possible?

You can pattern match in the function signature itself:
update msg (Model model) =
model.stack ...
or, if you want to use stack directly:
update msg (Model { stack }) =
...
As for whether you should do this type of thing? I've used it in the past when explicitly trying to hide implementation details from a model. You just have to be willing to deal with the extra verbosity that it inevitably introduces. It really is up to you to decide whether it is necessary. I would probably lean towards avoiding it unless there's an explicit need.

Related

Array of objects

Let's say I want to connect to two package repositories, make a query for a package name, combine the result from the repos and process it (filter, unique, prioritize,...), What is a good way to do that?
What I though about is creating Array of two Cro::HTTP::Client objects (with base-uri specific to each repo), and when I need to make HTTP request I call #a>>.get, then process the result from the repos together.
I have attached a snippet of what I'm trying to do. But I would like to see if there is a better way to do that. or if the approach mention in the following link is suitable for this use case! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/
use Cro::HTTP::Client;
class Repo {
has $.name;
has Cro::HTTP::Client $!client;
has Cro::Uri $.uri;
has Bool $.disable = False;
submethod TWEAK () {
$!client = Cro::HTTP::Client.new(base-uri => $!uri, :json);
}
method get (:$package) {
my $path = <x86_64?>;
my $resp = await $!client.get($path ~ $package);
my $json = await $resp.body;
return $json;
}
}
class AllRepos {
has Repo #.repo;
method get (:$package) {
# check if some repos are disabled
my #candidate = #!repo>>.get(:$package).unique(:with(&[eqv])).flat;
# do furthre processign of the data then return it;
return #candidate;
}
}
my $repo1 = Repo.new: name => 'repo1', uri => Cro::Uri.new(:uri<http://localhost:80>);
my $repo2 = Repo.new: name => 'repo2', uri => Cro::Uri.new(:uri<http://localhost:77>);
my #repo = $repo1, $repo2;
my $repos = AllRepos.new: :#repo;
#my #packages = $repos.get: package => 'rakudo';
Let's say I want to connect to two package repositories, make a query for a package name, combine the result from the repos and process it (filter, unique, prioritize,...), What is a good way to do that?
The code you showed looks like one good way in principle but not, currently, in practice.
The hyperoperators such as >>:
Distribute an operation (in your case, connect and make a query) ...
... to the leaves of one or two input composite data structures (in your case the elements of one array #!repo) ...
... with logically parallel semantics (by using a hyperoperator you are declaring that you are taking responsibility for thinking that the parallel invocations of the operation will not interfere with each other, which sounds reasonable for connecting and querying) ...
... and then return a resulting composite data structure with the same shape as the original structure if the hyperoperator is a unary operator (which applies in your case, because you applied >>, which is an unary operator which takes a single argument on its left, so the result of the >>.get is just a new array, just like the input #!repo) or whose shape is the hyper'd combination of the shapes of the pair of structures if the hyperoperator is a binary operator, such as >>op<< ...
... which can then be further processed (in your case it is, with .unique, which will produce a resulting Seq) ...
... whose elements you then assign back into another array (#candidate).
So your choice is a decent fit in principle, but the commitment to parallelism is only semantic and right now the Rakudo compiler never takes advantage of it, so it will actually run your code sequentially, which presumably isn't a good fit in practice.
Instead I suggest you consider:
Using map to distribute an operation over multiple elements (in a shallow manner; map doesn't recursively descend into a deep structure like the hyperoperators, deepmap etc., but that's OK for your use case) ...
... in combination with the race method which parallelizes the method it proceeds.
So you might write:
my #candidate =
#!repo.hyper.map(*.get: :$package).unique(:with(&[eqv])).flat;
Alternatively, check out task 94 in Using Perl 6.
if the approach mention in the following link is suitable for this use case! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/
I don't think so. That's about constructing a general purpose container that's like an array but with some differences to the built in Array that are worth baking into a new type.
I can just about imagine such things that are vaguely related to your use case -- eg an array type that automatically hyper distributes method calls invoked on it, if they're defined on Any or Mu (rather than Array or List), i.e. does what I described above but with the code #!repo.get... instead of hyper #!repo.map: *.get .... But would it be worth it (assuming it would work -- I haven't thought about it beyond inventing the idea for this answer)? I doubt it.
More generally...
It seems like what you are looking for is cookbook like material. Perhaps a question posted at the reddit sub /r/perl6 is in order?

Elm Language What do the Multiple Types in a row (without the arrow) in a signature mean?

In the Elm language, I'm having a hard time explaining my question...
In these snippets in elm:
I understand the signature in something like
update : Msg -> Model -> Model
where the parameters / output is separated by arrows, but how do I read / grok things like:
Sub Msg
Program Never Model Msg
In:
main : Program Never Model Msg
main =
program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
In a type signature, parameter types are separated by ->, with the last type being the return value.
If there are no -> symbols, then it means it is a value of that type. In your main example, the type of main is Program Never Model Msg. It has no arrows, so it takes no parameters.
Now, each parameter and the return value in the type annotation may have several things separated by spaces, as in your main example. The leftmost is the type, followed by type parameters separated by spaces.
Program Never Model Msg
| | | |
| ------|-----
type type parameters
A type parameter is similar to Generics in a language like C#. The equivalent syntax in C# would be:
void Program<Never, Model, Msg>()
C# doesn't directly correlate because it has a different way of constraining generic type parameters, but the general idea holds.
The Elm guide doesn't currently have a great deal of info, but here is the section talking about types.
Sub Msg, List Int, Program Never Model Msg
Sub, List and Program are type constructors. You can think about them as functions that take a type and return another type.
By themselves, Sub, List and Program are not complete type. They are like a puzzle missing a piece. When one adds the missing piece, the puzzle is complete.
I usually read them in my head using the word of as in a List of Ints, a Program of Never, Model and Msg.

populate object from command line and check object state

I populate an object based on the users input from the commandline.
The object needs to have a certain amount of data to proceed. My solution so far is nested if-statements to check if the object is ready. Like below example.
Maybe 3 if-statements aren't so bad(?) but what if that number of if-statements starts to increase? What are my alternatives here? Let's say that X, Y and Z are three completely different things. For example let's say that object.X is a list of integers and object.Y is a string and maybe Z is some sort of boolean to return true only if object.Y has a certain amount of values?
I'm not sure polymorhism will work in this case?
do
{
if (object.HasX)
{
if (object.HasY)
{
if (object.HasZ)
{
//Object is ready to proceed.
}
else
{
//Object is missing Z. Handle it...
}
}
else
{
//Object is missing Y. Handle it...
}
}
else
{
//Object is missing X. Handle it...
}
} while (!String.IsNullOrEmpty(line));
For complex logic workflow, I have found, it's important for maintainability to decide which level of abstraction the logic should live in.
Will new logic/parsing rules have to be added regularly?
Unfortunately, there isn't a way to avoid having to do explicit conditionals, they have to live somewhere.
Some things that can help keep it clean could be:
Main function is only responsible for converting command line arguments to native datatypes, then it pushes the logic down to an object builder class, This will keep main function stable and unchanged, except for adding flag descriptions, THis should keep the logic out of the domain, and centralized to the builder abstraction
Main function is responsible for parsing and configuring the domain, this isolates all the messy conditionals in the main/parsing function and keeps the logic outside of the domain models
Flatten the logic, if not object.hasX; return, next step you know has.X, this will still have a list of conditionals but will be flatter
Create a DSL declarative rule language (more apparent when flattening). This could be a rule processor, where the logic lives, then the outer main function could define that states that are necessary to proceed

How to declare variables with a type in Lua

Is it possible to create variables to be a specific type in Lua?
E.g. int x = 4
If this is not possible, is there at least some way to have a fake "type" shown before the variable so that anyone reading the code will know what type the variable is supposed to be?
E.g. function addInt(int x=4, int y=5), but x/y could still be any type of variable? I find it much easier to type the variable's type before it rather than putting a comment at above the function to let any readers know what type of variable it is supposed to be.
The sole reason I'm asking isn't to limit the variable to a specific data type, but simply to have the ability to put a data type before the variable, whether it does anything or not, to let the reader know what type of variable that it is supposed to be without getting an error.
You can do this using comments:
local x = 4 -- int
function addInt(x --[[int]],
y --[[int]] )
You can make the syntax a = int(5) from your other comment work using the following:
function int(a) return a end
function string(a) return a end
function dictionary(a) return a end
a = int(5)
b = string "hello, world!"
c = dictionary({foo = "hey"})
Still, this doesn't really offer any benefits over a comment.
The only way I can think of to do this, would be by creating a custom type in C.
Lua Integer type
No. But I understand your goal is to improve understanding when reading and writing functions calls.
Stating the expected data type of parameters adds only a little in terms of giving a specification for the function. Also, some function parameters are polymorphic, accepting a specific value, or a function or table from which to obtain the value for a context in which the function operates. See string.gsub, for example.
When reading a function call, the only thing known at the call site is the name of the variable or field whose value is being invoked as a function (sometimes read as the "name" of the function) and the expressions being passed as actual parameters. It is sometimes helpful to refactor parameter expressions into named local variables to add to the readability.
When writing a function call, the name of the function is key. The names of the formal parameters are also helpful. But still, names (like types) do not comprise much of a specification. The most help comes from embedded structured documentation used in conjunction with an IDE that infers the context of a name and performs content assistance and presentations of available documentation.
luadoc is one such a system of documentation. You can write luadoc for function you declare.
Eclipse Koneki LDT is one such an IDE. Due to the dynamic nature of Lua, it is a difficult problem so LDT is not always as helpful as one would like. (To be clear, LDT does not use luadoc; It evolved its own embedded documentation system.)

Lambdas with captured variables

Consider the following line of code:
private void DoThis() {
int i = 5;
var repo = new ReportsRepository<RptCriteriaHint>();
// This does NOT work
var query1 = repo.Find(x => x.CriteriaTypeID == i).ToList<RptCriteriaHint>();
// This DOES work
var query1 = repo.Find(x => x.CriteriaTypeID == 5).ToList<RptCriteriaHint>();
}
So when I hardwire an actual number into the lambda function, it works fine. When I use a captured variable into the expression it comes back with the following error:
No mapping exists from object type
ReportBuilder.Reporter+<>c__DisplayClass0
to a known managed provider native
type.
Why? How can I fix it?
Technically, the correct way to fix this is for the framework that is accepting the expression tree from your lambda to evaluate the i reference; in other words, it's a LINQ framework limitation for some specific framework. What it is currently trying to do is interpret the i as a member access on some type known to it (the provider) from the database. Because of the way lambda variable capture works, the i local variable is actually a field on a hidden class, the one with the funny name, that the provider doesn't recognize.
So, it's a framework problem.
If you really must get by, you could construct the expression manually, like this:
ParameterExpression x = Expression.Parameter(typeof(RptCriteriaHint), "x");
var query = repo.Find(
Expression.Lambda<Func<RptCriteriaHint,bool>>(
Expression.Equal(
Expression.MakeMemberAccess(
x,
typeof(RptCriteriaHint).GetProperty("CriteriaTypeID")),
Expression.Constant(i)),
x)).ToList();
... but that's just masochism.
Your comment on this entry prompts me to explain further.
Lambdas are convertible into one of two types: a delegate with the correct signature, or an Expression<TDelegate> of the correct signature. LINQ to external databases (as opposed to any kind of in-memory query) works using the second kind of conversion.
The compiler converts lambda expressions into expression trees, roughly speaking, by:
The syntax tree is parsed by the compiler - this happens for all code.
The syntax tree is rewritten after taking into account variable capture. Capturing variables is just like in a normal delegate or lambda - so display classes get created, and captured locals get moved into them (this is the same behaviour as variable capture in C# 2.0 anonymous delegates).
The new syntax tree is converted into a series of calls to the Expression class so that, at runtime, an object tree is created that faithfully represents the parsed text.
LINQ to external data sources is supposed to take this expression tree and interpret it for its semantic content, and interpret symbolic expressions inside the tree as either referring to things specific to its context (e.g. columns in the DB), or immediate values to convert. Usually, System.Reflection is used to look for framework-specific attributes to guide this conversion.
However, it looks like SubSonic is not properly treating symbolic references that it cannot find domain-specific correspondences for; rather than evaluating the symbolic references, it's just punting. Thus, it's a SubSonic problem.