How would you model a USB cable using interfaces so that the cable itself is unidirectional(different jacks) but in theory I could connect the "output" side to the "input" side but not input to input.
e.g., I'm trying to model the following
* -> + -> * -> + etc...
but never have something like * -> * -> ... or + -> + -> ...
but each * and + is basically interchangeable. I just want to make sure *'s go through the -> processes before they are allowed to be used again.
The idea is pretty simple, outputs can be used as inputs BUT inputs can be used as outputs... but inputs and outputs are pretty much interchangable data wise(just a stream of data).
(it seems I have to use an adapter pattern but I'd like to somehow use the composite pattern so I don't have to explicitly adapt anything. I'd like it just to work plug and play and have the appropriate connection chosen)
e.g.,
interface data;
interface input : data;
interface output : data;
this allows inputs to go to inputs or outputs.
Perhaps you could use (C# syntax) a structure as follows:
class Input
{
Output output;
}
class Output
{
Input input;
}
Then a chain of input -> output -> input could look like:
Input input1 = new Input();
Output output2 = new Output();
Input input3 = new Input();
output2.input = input1;
input3.output = output2;
Related
I have an application that I want to generate a list of 5 unique numbers on init three times after reading a json. So basically I want to get something like [31, 59, 62, 72, 2, 16, 2, 38, 94, 15, 55, 46, 83, 2, 10]. My challenge is that I am new to functional programming and elm and I am a bit lost. So I understand that Random.generate takes a msg and a generator and returns a cmd message and it is mostly used in the update function but this is not where I need as it is a helper function and doesn't need to communicate with the client. I think it can be used in init but I don't know how. Again my function is recursive and I don't know how to apply this logic with Random.generate recursively.
I understand my code will not work and I have tried it because Random.int does not generate a random number but a type of generate but still I don't know how to apply this to get what I want.
recursion : Int -> List a -> List number
recursion a b =
if List.length b > 5
then b
else
let
rand = Random.int 0 a
in
if(List.member rand b)
then recursion a b
else
recursion a (rand :: b)
can be called with:
recursion 50 []
I want to generate a list/array of 5 unique random 3 times.
Great question. There are two parts here:
- generating random numbers, and
- wiring this all up
You will need the Random library for the former, and a little inspection will lead you to something like
get15Randoms = Random.generate OnRandomNumbers <| Random.list 5 (int 0 100)
This has type Cmd Msg - it's an async operation that will return on a Msg.
Wiring it up will be a series of stages. You refer to doing it in 'init' but that's not how Elm is going to work for you here. In the init function you can start off your json request. Then you'll need something like
init = ( initModel
, Http.get {url =..., expect = Http.expectJson OnJson yourDecoder}
)
update msg model =
case msg of
OnJson (Ok data) ->
-- attach json
( {model | data = data }, get15Randoms )
OnRandomNumbers ints ->
( { model | ints = ints }, Cmd.none )
In other words, once the json comes back you can attach that, and use that iteration of the update to launch your random number request, and then catch the result in a subsequent iteration
Random number generation is a side-effect because it's not predictable by definition, meaning its output isn't purely determined by its inputs. In Elm all side-effects go through the update function because if side-effects were allowed anywhere there would be no guarantee that any part of your code is pure and predictable. Things might start behaving differently at random, and it would be very hard figure out why since random input can occur anywhere.
That said, init is one place where it might make sense to allow side-effects, since there isn't any state yet. But since most side-effects are not immediate and you would most likely want to present some UI to indicate that your app is loading, I assume the API just hasn't been complicated to allow for a use case so rare. Especially since there are a couple workarounds you can use:
Workaround 1 - an empty representation
Since you're using a list to contain the random numbers, you could probably just use an empty list to represent that you've not received the numbers yet. Otherwise use a Maybe, or a custom type. This might be a bit cumbersome since you have to handle the empty case every time you use it, but depending on your use case it might be acceptable.
Workaround 2 - flags
Elm allows for sending data into your program from the outside on initializtion, and will pass this to your init function. This mechanism is called flags. You can use this to generate the numbers in JavaScript before sending it in as a parameter.
In your index.html you would put:
var app = Elm.Main.init({
node: document.getElementById('elm'),
flags: Array.from({length: 15}, () => Math.floor(Math.random() * 50))
});
And in init you accept the numbers as an ordinary argument:
init : List number -> Model
init numbers =
{ myNumbers = numbes
, ...
}
I want to respond with what I ended up doing motivated by #Simon-h's answer. I had a Msg type RndGen Int and since update is a function I decided to call RndGen recursively with help from the update function and flag it off when I got the number of random numbers I needed.
update msg model =
case msg of
NoOp ->
(model, get15Randoms)
RndGen rndGen ->
if List.length (model.questions) < 15
then
if List.member rndGen model.questions
then
(model, get15Randoms)
else
({model | questions = rndGen :: model.questions }, get15Randoms)
else
(model, Cmd.none)
and
get15Randoms =
Random.generate RndGen (Random.int 0 100)
on init
init questions =
(Model (getQuestions questions) 1 True [] False "", get15Randoms)
I will like to know if my thinking aligns with what the elm community will expect.
I want to get List out of Generator
intList : Generator (List Int)
intList =
list 5 (int 0 100)
How could I now get a list out of it?
You cannot get a random list out of Generator because Elm functions are always pure. The only possibility to get a list is to use a command.
A command is a way to tell Elm runtime to do some impure operation. In your case, you can tell it to generate a random list of integers. Then it will return back the result of that operation as an argument of the update function.
To send Elm runtime a command to generate a random value, you can use the function Random.generate:
generate : (a -> msg) -> Generator a -> Cmd msg
You already have Generator a (your intList), so you need to provide a function a -> msg. This function should wrap a (List Int in your case) into a message.
The final code should be something like that:
type Msg =
RandomListMsg (List Int)
| ... other types of messages here
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model = case msg of
... -> ( model, Random.generate RandomListMsg intList)
RandomListMsg yourRandomList -> ...
If you don't know about messages and models yet, you should probably get acquainted with the Elm architecture first.
You can provide your own seed value to Random.step, which will return a tuple containing a list and the next seed value. This retains purity because you will always get the same result when you pass the same seed.
Random.step intList (Random.initialSeed 123)
|> Tuple.first
-- will always yield [69,0,6,93,2]
The answer given by #ZhekaKozlov is typically how you generate random values in an application, but it uses Random.step under the hood with the current time used as the initial seed.
We have data packets with different structures. They are supposed to be read/written in different languages. Example:
| ClassId | Data |
ClassId = "datapoint" (Data structure):
temperature - 1bytes
elevation - 2bytes
gradient - 1bytes
ClassId = "config" (Data structure):
frequency - 1bytes
deviceId - 3bytes
ClassId = "accelerometer" (Data structure):
time - 2bytes
x - 2bytes
y - 2bytes
z - 2bytes
Rather than manually writing the code that parses each data packet based on its class (which is error prone and time-consuming), I would expect to have a configuration file and then the code (python/c/etc.) is generated automatically that can read and write packets. Something along these lines:
lib.set(packet, "datapoint", {
elevation: 933,
temperature: 18,
gradient: 20
});
lib.get(packet, "datapoint");
=>
{
elevation: 933,
temperature: 18,
gradient: 20
}
Googling it did not bring me anywhere. Any pointers would be very helpful.
You need a code generation system, that compiles a packet specification into code to parse/unparse the packets.
You can build one ad hoc using a parser generator, and write ad hoc code to procedurally walk a parse tree and spit out relevant code.
Or you can use a program transformation system (PTS), which treats your packet specifications like source code, and transforms to source code in your target language. You explain the syntax of the packets to the PTS pretty much the same way you explain the syntax to a parser generator.
But with a PTS, you can write transformation rules in surface syntax notation that recognizes the packet-system syntax and maps it to target langauge function syntax. That makes writing and maintaining such a tool a lot easier, especially if the packet syntax changes, and/or you change the target language infrastructure to parse the packets in different ways.
EDIT 10/3: OP asks for a concrete example, presumably with a PTS.
I'm going to show what this looks like for our DMS Software Reengineering Toolkit (see bio for more about DMS).
First you need an (DMS-compatible) grammar for the packet languages. Based on what I see, it is pretty simple:
Packets = Packet ;
Packets = Packets Packet ; -- allow a list of packet defintions
Packet = 'ClassID' '=' STRING members ;
members = ;
members = members member ; -- allow list of members
member = IDENTIFIER '-' NATURAL 'bytes' ;
I think this grammar is naive in that packet members in practice may have different types (maybe strings, floats, booleans, ...); OP's example only shows what I'm assuming are N-byte binary integer numbers. You also need grammars for your various target languages. I'm going to assume you have these grammars (and that's quite the assumption); lets work with C for the moment. [DMS does have many of these].
We also have to assume a representation of the transmitted data. OP suggests something but I think he is trying to hint at generated code ("lib.set...").
Instead I'm going to assume that packet content is being read from a Stream as binary bytes simply appended together; this makes for the smallest packet size possible and thus fast transmission times.
So, now we to specify our code generator, as set of rewrite rules that map packet definitions to code.
For background, a rewrite rule for a PTS typically looks like this:
if you see *this*, replace it by *that*
So you are essentially replacing one structure by another. These typically operate on ASTs, but use surface syntax for this and that for readability.
What follows are DMS's source to source rewrite rules; they look like they operate on text but in fact they operate on ASTs produced by DMS's parser.
DMS has its own syntax for rules but it essentially follows the typical style above:
rule rule_name( pattern_variables ):
source_syntax_category -> target_syntax_category =
" this_pattern " -> " that_pattern " ;
Source and target patterns are enclosed in *metaquotes" "; actual literal quote characters are thus escaped as \".
For DMS rules this is always a fragment of the Packet notation, and that is always a fragment of our chosen target language (C). Pattern variable names in the rule head are given syntactic types and can only match the corresponding type in the AST. Pattern variables found inside metaquotes are written as \variable. Metafunctions can compute derived results; they are invoked inside patterns as "\function( args )". See DMS Rewrite Rules for more details.
source domain Packet; -- the little language we defined
target domain C; -- what we will generate code for
-- you'll write one of these rulesets for each target language
rule top_level(pl: Packets): Packets -> Statements =
" \pl "
-> " ReadPacketType(stream, packet_type);
switch(packet_type) {
\pl
default: Panic(\"unrecognized packet type\");
}" if IsRoot(pl); -- do this once [at root of tree]
rule translate_packet_definitions(p: Packet, pl: packet_list): Packets -> switch_case_list
" \p \pl ";
rule translate_packet_definition(s:STRING, ms: members, pl: Packets): Packets -> switch_case =
" ClassID = \s \m \pl "
-> " case \concatenate\(\"enum_\"\,\string_to_identifier\(\s\)\): {
\string_to_identifier\(\s\)* p=malloc(sizeof(\string_to_identifier\(\s\)));
\m
return p;
}
";
rule translate_members(m: member, ms: members) : members -> Statements
= " \m \ms ";
rule translate_member(i: IDENTIFIER, n: NATURAL) = member -> StatementList =
" \i - \n bytes " ->
" p-> \toCIdentifer\(\i\) = ReadNByteValue(stream,\toCNatural\(\n\)) ; "
This isn't complete (in particular, I need anther set of rules to generate the enum declaration for the set of packet types) and I doubt if it is exactly right but it give the flavor of the rules. With these rules, OP's example input would generate this C code:
ReadPacketType(stream, packet_type);
switch(packet_type) {
case enum_datapoint: {
datapoint* p=malloc(sizeof(datapoint));
p->temperature=ReadNByteValue(stream,1);
p->elevation=ReadNByteValue(stream,2);
p->gradient=ReadNByteValue(stream,2);
return p;
}
case enum_config: {
config* p=malloc(sizeof(config));
p->frequency=ReadNByteValue(stream,1);
p->deviceId=ReadNByteValue(stream,3);
return p;
}
case enum_accelerometer: {
accelerometer* p=malloc(sizeof(accelerometer));
p-time>=ReadNByteValue(stream,2);
p->x=ReadNByteValue(stream,2);
p->y=ReadNByteValue(stream,2);
p->z=ReadNByteValue(stream,2);
return p;
}
default: Panic(\"unrecognized packet type\");
}
The following Chisel code works as expected.
class Memo extends Module {
val io = new Bundle {
val wen = Bool(INPUT)
val wrAddr = UInt(INPUT, 8)
val wrData = UInt(INPUT, 8)
val ren = Bool(INPUT)
val rdAddr = UInt(INPUT, 8)
val rdData = UInt(OUTPUT, 8)
}
val mem = Mem(UInt(width = 8), 256)
when (io.wen) { mem(io.wrAddr) := io.wrData }
io.rdData := UInt(0)
when (io.ren) { io.rdData := mem(io.rdAddr) }
}
However, it's a compile-time error if I don't specify io.rdData := UInt(0), because defaults are required. Is there a way to either explicitly specify X or to have modules without defaults output X, erm, by default?
Some reasons you might want to do this are that nothing should rely on the output if ren isn't asserted, and Xs let you specify it, and specifying an X can tell the synthesis tool that it's a don't care, for optimization purposes.
Chisel does not support X.
This is probably what you want:
io.rdData := mem(io.rdAddr)
(this prevents muxing between zero and mem's readout data).
If, for example, one is trying to infer a single-ported SRAM, the Chisel tutorial/manual describes how to do so (https://chisel.eecs.berkeley.edu/latest/chisel-tutorial.pdf):
val ram1p =
Mem(UInt(width = 32), 1024, seqRead = true)
val reg_raddr = Reg(UInt())
when (wen) { ram1p(waddr) := wdata }
.elsewhen (ren) { reg_raddr := raddr }
val rdata = ram1p(reg_raddr)
In short, the read address needs to be registered (since we're dealing with synchronous memory in this example), and the enable signal on this register dictates that the read-out data only changes with that enable is true. Thus, the backend understands this a read-enable signal exists on the read port, and in this example, the write port and the read port are one and the same (since only one is ever accessed at a time). Or if you want 1w/1r (as per your example), you can change the "elsewhen (ren)" to a "when (ren)".
From the Chisel 2.0 Tutorial paper, only binary logic is supported at the moment:
2 Hardware expressible in Chisel
This version of Chisel also only supports binary logic, and does not
support tri-state signals.
We focus on binary logic designs as they constitute the vast majority
of designs in practice. We omit support for tri-state logic in the
current Chisel language as this is in any case poorly supported by
industry flows, and difficult to use reliably outside of controlled
hard macros.
I'm working on an online judge for algorithm contests. I want to include support for many programming languages, but i don't know all of them. I have to make test sources, but i don't know all of these languages.
I want the equivalent of this code:
#include <stdio.h>
int main () {
int a, b;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d%d", &a, &b);
printf("%d", a + b);
return 0;
}
In this programming languages.
I want to read from file input.txt two numbers, each on a line, and write the sum of them to the output file output.txt
Thank you.
EDIT Please don't tell me that Visual Basic .NET is not a functional language. I know it.
Haskell:
main = do
[astr, bstr] <- fmap lines (readFile "input.txt")
writeFile "output.txt" $ show (read astr + read bstr)
Or to sum all lines:
main = writeFile "output.txt" . show . sum . map read . lines =<< readFile "input.txt"
In F#:
System.IO.File.ReadAllLines "input.txt" |> Seq.sumBy int |> string
|> fun s -> System.IO.File.WriteAllText("output.txt", s)
An F# version that assumes that the input file contains just two lines (with numbers):
open System.IO
let [| astr; bstr |] = File.ReadAllLines "input.txt"
File.WriteAllText("output.txt", string (int astr + int bstr))
This is a bit simpler than Jon's version, but it is a more direct solution (and behaves the same as Haskell solution posted by others).
There are a ton of ways of doing this in Scala.
val f = (as : Array[String]) => as(0).toInt + as(1).toInt
io.Source.fromFile("C:/myfile.xtx").getLines().toStream match {
case line1 #:: _ => println(f(line1.split(","))
}
You could also do...
val splitLine = (_ : String).split(",")
val printSum = (as : Array[String]) => println(as(0).toInt + as(1).toInt)
val sums = io.Source.fromFile("C:/f.xtx").getLines() map (splitLine andThen printSum)
sums.head //start printing as Iterator is lazy
But then since side-effects should generally be avoided, you would probably want to make your functions pure
val sumLine = (as : Array[String]) => as(0).toInt + as(1).toInt
val sums = io.Source.fromFile("C:/f.xtx").getLines() map (splitLine andThen sumLine)
println(sums.head)
Some answers here seem confused about what the C code does. The C code is not particularly useful. It takes a file like
42
1776
this is any sort of random junk
because the program never reads this far
and produces a file containing
1818
and that is it. IMO, this is a lousy example for showing the power of functional languages because it does so little--one instance of one operation, basically. Yawn. With about the same amount of work, you could take a file with two columns of numbers and produce a file that had their sum in one column as an output. With a tiny bit more work, you could handle any conceivable error in the input.
But, fair enough, if this is the job at hand, one way to accomplish this in Scala is:
val pw = new java.io.PrintWriter("output.txt")
val num = scala.io.Source.fromFile("input.txt").getLines().map(_.toInt)
pw.print(num.next+num.next)
pw.close // Only use this line if execution continues (e.g. in REPL)
Racket Scheme:
(define (simpleSum)
(let* ((input (map string->number (file->lines "input.txt")))
(a (first input)) (b (second input)))
(write-to-file (number->string (+ a b)) "output.txt")))
I don't think scala has its advantage in such simple scenario, including all its fancy features and its api. It's better to use java library. java.util.Scanner has provided the useful nextInt() which can work in many cases and PrintWriter is the fastest output mechniasm in java.
val in = new Scanner(new FileInputStream("input.txt"))
val out = new PrintWriter("output.txt")
out.println((in.nextInt + in.nextInt))
out.close
in.close
And also, I'm curious about which online judge you're working on :)
Here is the VB.NET implementation:
Dim FileLines() as string = system.io.file.readalllines("input.txt")
system.io.file.WriteAllText("output.txt", ctype(FileLines(0), integer) + ctype(FileLines(1), integer))
Visual Basic is not a functional language, unless you use some of the LINQ features.