I am trying to swap elements in a list in ML. My swap function returns the error inserting EQUALOP.
fun swap(n:int, i:int, deck:card list) =
local
val card1_removed = nth(deck,i)
val card2_removed = nth(deck,n)
in
val deck = remove(deck,i)
val deck = remove(deck,n)
val deck = insert_at(deck,n,card1_removed)
val deck = insert_at(deck,i,card2_removed)
print_cards(deck);
end;
Any suggestions?
There are a few problems with your code.
First off you cant have a local declaration inside a function definition like that. The body of a function must be an expression, and local ... in .. end is a declaration. In this case you have to use let ... in .. end, which is an expression.
Note that you can't have value declarations in the in ... end part of a let-expression though. Here you will have to move all the value declarations up in the let ... in part.
To be a bit more clear the form of let and local is:
<atexp> ::= let <dec> in <exp_1> ; ... ; <exp_n> end
<dec> ::= local <dec_1> in <dec_2> end
Thus, normally local is used like this
local
fun foo ...
val ....
in
fun swap ...
end
where let is used like this
fun swap ...
let
val ...
in
..
end
Related
class Foo
def initialize(#foo : String | Nil)
end
def foo
#foo
end
end
a = Foo.new "213"
if !a.foo.nil?
puts a.foo, typeof(a.foo)
end
get output of
213
(String | Nil)
but shouldn't type of a.foo be narrowed to String? Is this another design limit?
The compiler doesn't know that #foo doesn't change. Say your class Foo has a setter for #foo. If some concurrently running code uses that setter to set #foo to nil, the second call to Foo#foo inside the if condition might return nil now even though the check passed before.
You can remedy by introducing a local variable which the compiler can reason about:
if foo = a.foo
puts foo, typeof(foo)
end
I'm learning OCaml, and I'm a bit confused with the immutability of variables. According to the book I'm reading, variables are immutable. So far so good, but why on Earth can I do this:
let foo = 42
let foo = 4242
What am I missing??
I think the best way to explain is with an example. Consider this code (executed in the OCaml REPL):
# let foo = 42;;
val foo : int = 42
# let return_foo () = foo;;
val return_foo : unit -> int = <fun>
# let foo = 24;;
val foo : int = 24
# return_foo ();;
- : int = 42
The above code does the following:
Binds 42 to the name foo.
Creates a function return_foo () that returns the value bound to foo.
Binds 24 to the name foo (which hides the previous binding of foo).
Calls the return_foo () function, which returns 42.
Compare this with the behaviour of a mutable value (created using ref in OCaml):
# let foo = ref 42;;
val foo : int ref = {contents = 42}
# let return_foo () = !foo;;
val return_foo : unit -> int = <fun>
# foo := 24;;
- : unit = ()
# return_foo ();;
- : int = 24
which:
Creates a mutable reference containing 42 and binds it to the name foo.
Creates a function return_foo () that returns the value stored in the reference bound to foo.
Stores 24 in the reference bound to foo.
Calls the return_foo () function, which returns 24.
The name foo is first bound to an immutable value 42 and later it is rebound to another immutable value 4242. You can even bind the same name to variables of different types. In OCaml we are talking not about mutability of a variable, but about a mutability of a value. For example, if you bind foo to an array of values, this would be the same name, but bound to a mutable data, so that the value of a variable can change in time. Finally, each new binding just hides the previous one, so the original foo is still bound to 42, but it is invisible and will garbage collected.
Maybe a little example will clarify the idea:
let example () =
let foo = 42 in (* 1 *)
let foo = 4242 in (* 2 *)
let foo = [|42|] in (* 3 *)
foo.(0) <- 56 (* 4 *)
It might be easier to have the following mental model:
(*1*) +--------+
+----> | 42 |
+------------+ | +--------+
| +----+
| foo +----+ +--------+
| | +----> | 4242 |
+---------+--+ (*2*) +--------+
|
| (*3*) +--------+
+------------> |[| 42 |]|
(*4*) +--------+
On lines 1 and 2 we just bind a variable foo to two different values. On line 3 we bind it to an array that contains one element. On line 4, we change the value, and foo is still bound to the same value, but the value contains different datum.
I hope I didn't confuse you even more ;)
The usual form of let is the let ... in expression, where you define a variable binding, which only exists in the inside of the body of the let. The body of the let is a new scope.
let x = 42 in (* body here *)
Here the "body" of the let is a new scope that is different from the one outside, with all the variables from the outside with an additional local variable x that is only defined in the body of this let.
Now you are talking about lets at the top level of the file. These look a little different syntactically (there is no in), but really they are the same, with the "body" being the rest of the file. So here you can think of the rest of the file after the let as a new scope, with x being a local variable of this scope. So your code is equivalent to this:
let foo = 42 in (
let foo = 4242 in (
(* rest of file *)
)
)
Here your inner let binds a local variable that has the same name as a variable that already exists in the outer scope. That doesn't matter. You are binding a new variable in an inner scope. If it happens to have the same name as a variable in an outer scope, then code in the inner scope referencing that name will refer to the innermost binding. The two variables, however, are completely independent.
In a C-like language, it would be something like this:
{
const int foo = 42;
{
const int foo = 4242;
// rest of code here
}
}
See? There is no assignment to any variables here.
What I am trying to achieve is similar to a logging facility but for monitoring and streaming arbitrary data from a running simulation. Here is the simplified situation:
module Sim (V:VEC) = struct
module V = V
module M = struct type data = V.t end
let loop n init_data =
let running_data = ref init_data in
for _i = 1 to n do
(*?*) (* monitor here: data => outside world *)
rdata := process_data !rdata
done
end
While simulation loops, at the ? I may want to 'tap' data and accumulate it. Other times, I want to just let it run and disable the data stream with minimal overhead -- the ? is in a tight loop. So I want the streaming to be configurable with little cost.
What I have now is this:
module Sim (V:VEC) = struct
module V = V
module M = struct type data = V.t end
let data_monitor : (M.data -> unit) ref = ref (fun d -> ())
let loop n init_data =
let running_data = ref init_data in
for _i = 1 to n do
!data_monitor !rdata; (* monitor here *)
rdata := process_data !rdata
done
end
Ie. I put a stub monitoring function reference in there. In the actual application script I can then assign a function which e.g. accumulates the data values into a list or some such. It works.
So the question is: is this the best/lowest overhead/nicest way to achieve what I want?
This approach seems a bit hackish, I would rather use the module system instead of function pointers. However, the data type to be streamed is only defined inside the functor Sim. So making a monitoring function in another module Sampler outside of Sim and parametrizing Sim by that, seems not convenient and/or requires duplication of code or recursive modules. I tried, but I was not able to make all types equal.
Edit: Here is roughly what it tried without function refs:
module Sampler (V:VEC) : sig
module V : VEC
type data = V.t
val monitor_data : data -> unit
end
with type data = V.t = struct
module V = V
type data = V.t
let monitor_data data = store_away_the data
end
module Sim (V:VEC) (Sampler:??) : sig
...
end with type M.data = V.t
At the ?? I was not sure how to specify the output signature of Sampler, since the input signature VEC is still free; also I was not sure how exactly to make the type equality work. Maybe I'm doing it wrong here.
As discussed in the comments, you may be able to do something like this using higher-order functions (instead of having to resort to a higher-order functor):
module type VEC = sig type t end
module Vec = struct type t = unit end
module Sim (V : VEC) =
struct
module M = struct type data = V.t list end
let process x = x
let rec loop ?(monitor : M.data -> unit = ignore) n data =
if n <= 0 then data
else
(monitor [];
process data |> loop ~monitor (n - 1))
end
module MySim = Sim (Vec)
let monitor _ = print_endline "foo"
let () =
MySim.loop ~monitor 5 ()
loop above takes an optional function as argument, which you can pass with the syntax ~monitor:my_fun or ~monitor:(fun data -> ...). If you already have a value called monitor in scope, you can simply do ~monitor to pass it. If you don't pass anything, the default value is ignore (i.e. fun _ -> ()).
I also rewrote loop in recursive style. The code above prints foo 5 times. Note that your monitor function can still come from Sampler module, you just have no need to pass the whole module in when instantiating Sim.
EDIT: If you still want to declare a higher-order functor, here is how you do it (...)
EDIT 2: Changed the example given additional information that the reason for the higher-order functor is that there are multiple monitoring functions to call. Note that in this case, there are still other solutions besides a higher-order functor: you could group the functions into a record, and pass the record to loop. Similar to this, you could pass a first-class module. Or, you could create one function that takes a variant type whose cases indicate at what stage the monitoring function is being called, and carry the data associated with each stage. You can also use classes for this, though I wouldn't recommend it. The functor approach does have an advantage, however, if you are committed to declaring M inside Sim.
I have omitted the signature VEC from the sketch because I'm under the impression that the questioner understands where to add it, and there is no problem with it :)
module type SAMPLER =
sig
type data
val monitor : data -> unit
val monitor' : data list -> unit
end
(* These are created inside Sim. *)
module type DATA =
sig
type data
val show : data -> string
end
(* Note that I am using destructive substitution (:=) to avoid the need
to have a type data declared in the body of MySampler below. If you
use a regular type equality constraint, you need to add a field
"type data = Data.data" to the body. *)
module type SAMPLER_FN =
functor (Data : DATA) -> SAMPLER with type data := Data.data
(* This is the higher-order functor (it takes another functor as an
argument). *)
module Sim (Sampler_fn : SAMPLER_FN) =
struct
(* Corresponds to module "Sim.M" in the question. *)
module Data =
struct
type data = string
let show s = s
end
(* Note that without additional type constraints or rearrangements,
the type data is abstract to Sampler (more precisely, Sampler_fn
is parametric over Data). This means that Sampler_fn can't
analyze values of type data, which is why we need to provide
functions such as Data.show to Sampler_fn for instances of
Sampler_fn to be "useful". If you are trying to avoid this and
are having trouble with these specific constraints, let me
know. The ability to pass types and related values (functions
in this case) to Sampler_fn is the main argument in favor of
using a higher-order functor. *)
module Sampler = Sampler_fn (Data)
let simulate x =
(* Call one monitoring function. *)
Sampler.monitor "hi!";
(* Do some computation and call another monitoring function. *)
Sampler.monitor' ["hello"; "world"]
end
Usage:
module MySampler (Data : DATA) =
struct
let monitor data = data |> Data.show |> print_endline
let monitor' data =
data
|> List.map Data.show
|> String.concat " "
|> print_endline
end
module MySim = Sim (MySampler)
let () = MySim.simulate ()
This prints
hi!
hello world
For completeness:
Building on the functor part of antron's answer, this is what I am currently using. It is still a bit involved, and maybe it could be made more concise, but it has some nice advantages. Namely: the monitoring of individual aspects can be switched on and off in a centralized place (a module of type SAMPLER) and arbitrary types can be exported, even if they become defined only somewhere inside the simulator module.
I define the monitoring (=sampling) modules and module types like so:
module type STYPE = sig type t end
module type SSAMPLER = sig
type t
val ev : t React.event
val mon : t -> unit
end
module type SAMPLER_FN = functor (Data : STYPE) -> SSAMPLER
with type t := Data.t
(* stub sampler function for a single one *)
module Never : SAMPLER_FN = functor (Data : STYPE) -> struct
let ev = React.E.never
let mon = ignore
end
(* event primitive generating sampling function *)
module Event : SAMPLER_FN = functor (Data : STYPE) -> struct
let (ev : Data.t React.event), mon' = React.E.create ()
let mon = mon' ?step:None
end
Here, I am using the React library to generate output streams of data. The React.E.never event does nothing and corresponds to sampling being switched off. Then the full sampling configuration is specified like so:
(* the full sampling config *)
module type SAMPLER = sig
val sampler_pos : (module SAMPLER_FN)
val sampler_step : (module SAMPLER_FN)
(* and several more... *)
end
module NoSampling : SAMPLER = struct
let sampler_pos = (module Never: SAMPLER_FN)
let sampler_step = (module Never: SAMPLER_FN)
(* ... *)
end
(* default sampling config *)
module DefaultSampling : SAMPLER = struct
include NoSampling
(* this is only possible when using first class modules *)
let sampler_pos = (module Event : SAMPLER_FN)
end
One could avoid the first-class modules, but then the convenient inclusion and override in DefaultSampling would not be allowed.
In the simulation library code this is used like this:
module type VEC = sig
type t
val zeropos : t
val wiggle : t -> t
end
module Sim (V:VEC) (Sampler:SAMPLER) = struct
module V = V
module M = struct
type t = { mutable pos : V.t }
val create () = { pos=V.zeropos }
module Sampler_pos = (val Sampler.sampler_pos) (struct type nonrec t = t end)
let update f m = m.pos <- f m.pos
end
module Sampler_b = (val Sampler.sampler_b) (struct type t = int end)
let loop n (running_data:M.t) =
for i = 1 to n do
(* monitor step number: *)
Sampler_b.mon i;
(* monitor current pos: *)
Sampler_pos.mon running_data;
M.update V.wiggle running_data
done
end
Here, the sampling functors are applied at appropriate places in the simulation loop. (val ...) is again necessary only because of the first class module wrapping.
Finally, in an application script, one would then do this:
module Simulator = Sim (V) (DefaultSampling);;
let trace = Simulator.M.Sampler_pos.ev
|> React.E.fold (fun l h -> h :: l) []
|> React.S.hold [];;
let init_m = Simulator.M.create () in
Simulator.loop 100 init_m;;
React.S.value trace;;
The last line then contains the accumulated list of values of type Simulator.M.t that occurred during the loop. Monitoring of the step counter (a silly example) is switched off. By making another sampling functor of type SAMPLER and parametrizing Sim by that, one could further customize the monitoring, if desired.
So my short code snippet looks like the following:
Source.fromFile(fileName).getLines().foldLeft(List[CsvEntry]())((csvList, currentLine) =>
currentLine match {
case pattern(organisation,yearAndQuartal,medKF,trueOrFalse,name,money) => new CsvEntry(organisation,yearAndQuartal,medKF.toInt,trueOrFalse.toInt,name,money) :: csvList
case default => csvList
The "fileName" is only the Name of the file, but it doesn't matter for my question.
And my csvList is defined like this:
type csvList = List[CsvEntry]
val list: csvList = List()
my class look like this:
class CsvEntry(val organisation: String, val yearAndQuartal : String, val medKF:Int, val trueOrFalse: Int, val name: String, val money:String){
override def toString = s"$organisation, $yearAndQuartal, $medKF,$trueOrFalse, $name, $money"
So my question is, whenever I am loading a file and writing it to my csvList it works, but when I am loading another 2nd file the old content gets overwirtten.
How can I change it in order to not get overwirtten, so it should only add it to the preceding data ?
The call beginning Source.fromFile... returns a list that you should then combine with the next call.
For example:
List("filename1", "filename2").map(processFile).flatten
where processFile is:
def processFile(fileName: String) = {
Source.fromFile(fileName).getLines().foldLeft... all the code in question
}
Nothing here can possibly get "overwritten", since there's no mutable state. Your type csvList and csvList in your foldLeft call are two very different things: the former is the type, the latter is the parameter.
Each time your snippet is executed, it returns a list of your CSV objects of a particular file. As an immutable list.
What you want is:
Make a function out of your snippet: def readFile(name: String): List[CsvFile]
Call it on the two files and save results to vals
Concat the two lists: list1 ++ list2
What is difference between plus and plusElement (minus, minusElement) functions over the (immutable) List in practice?
operator fun <T> Collection<T>.plus(element: T): List<T>
fun <T> Collection<T>.plusElement(element: T): List<T>
Besides plus and minus being operators and therefore simplifiable to + and - respectively, I wanted to share an example, that may make it more clear, why plusElement or minusElement may also make sense to use. Basically that's the case when you do not want the overloaded operator methods to be called (e.g. plus(elements : Iterable<T>)), which may be the case when you are dealing with a list of lists.
Maybe the following samples make that clearer. In the samples all variable assignments show the type they got assigned when calling the respective function and contain the result in the comment at the end of the line. The variable ~ending naming convention is the following:
PlusT show calls to plus(element : T)
PlusIterable show calls to plus(elements : Iterable<T>)
PlusElementT show calls to plusElement(element : T)
Samples:
val someEntry = "some entry"
val listOfSomeEntry = listOf(someEntry)
val los : List<String> = listOf("listOfString")
val lsPlusT : List<String> = los.plus(someEntry) // [listOfString, some entry]
val lsPlusIterable1 : List<String> = los.plus(listOfSomeEntry) // [listOfString, some entry]
val lsPlusIterable2 : List<Any> = los.plus(listOf(listOfSomeEntry)) // [listOfString, [some entry]]
val lsPlusElementT1 : List<String> = los.plusElement(someEntry) // [listOfString, some entry]
val lsPlusElementT2 : List<Any> = los.plusElement(listOfSomeEntry) // [listOfString, [some entry]]
val lol : List<List<String>> = listOf(listOf("listOfList"))
// the following is basically not really correct as we are now dealing with a list of lists of strings, but it shows that llPlusT and llPlusIterable lead to the same (in this case probably wrong) result..
val llPlusT : List<Any> = lol.plus(someEntry) // [[listOfList], some entry]
val llPlusIterable : List<Any> = lol.plus(listOfSomeEntry) // [[listOfList], some entry]
val llPlusIterable2 : List<List<String>> = lol.plus(listOf(listOfSomeEntry)) // [[listOfList], [some entry]]
val llPlusElement1 : List<Any> = lol.plusElement(someEntry) // [[listOfList], some entry]
val llPlusElement2 : List<List<String>> = lol.plusElement(listOfSomeEntry) // [[listOfList], [some entry]]
As you can see when using + the overloaded variant plus(elements : Iterable<T>) might be used, which will probably make sense in most cases, but may not make sense in some others, e.g. (most of the times) when dealing with a list of lists. Instead of forcing the + to add a list of lists by using + listOf(anotherList), you may rather want to use plusElement (plusElement(anotherList)) or if you are sure you want to add only a single element, you may want to omit plus in favor of plusElement (probably a very rare and very special use case... that would be reflected with variant llPlusElement1).
Finally the plusElement or minusElement make it really clear from the naming that what you pass reflects 1 single item of the list, whereas + leaves that basically open... (you should see that however from the context, which with a list of list is probably not that clear anyways ;-)). And a disclaimer at the end: that should not mean that you should use a list of lists, but just in case you find something like that you have plus/minusElement at hand ;-)
The first one is an overloaded operator, as indicated by the operator keyword. It allows you to use the + operator with a List<T>.
The second one is a regular function, called in the normal function call style.
Both return a new List<T> with the element appended.
Transcript from the Kotlin REPL:
>>>val a = listOf(1, 2, 3)
>>>a + 4
[1, 2, 3, 4]
>>> a.plusElement(4)
[1, 2, 3, 4]
For more information about Kotlin operator overloading, see https://kotlinlang.org/docs/reference/operator-overloading.html.