I'm studying OCaml and and doing various exercises on ordering data.
I would like to understand how to use the standard librari List for ordering
For example I would like to sort this array using these functions [94; 50; 6; 7; 8; 8]
List.sort
List.stable_sort
List.fast_sort
List.unique_sort
What is the syntax to do it ?
If you want to use these functions on your list, you have to specifiy the comparison function.
Quote from the documentation:
The comparison function must return 0 if its arguments compare as
equal, a positive integer if the first is greater, and a negative
integer if the first is smaller
In the module Pervasives you have a polymorphic comparison function:
val compare : 'a -> 'a -> int
So, in your case you can just do:
List.sort compare [94; 50; 6; 7; 8; 8]
Related
I am writing a function that will take a list of list and merge it into sorted pairs of list. For example [[1],[9],[8],[7],[4],[5],[6]] would return [[1,9],[7,8],[4,5],[6]]. This is my first attempt at SML. I keep getting this error: operator and operand don't agree [overload conflict].
fun mergePass[] = []
| mergePass(x::[]) = x::[]
| mergePass(x::y::Z) =
if x<y
then (x # y)::mergePass(Z)
else (y # x)::mergePass(Z);
Edit: If mergePass is called on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]].
This merge function takes two sorted lists
fun merge([],y) = y
| merge(x,[]) = x
| merge(a::x,b::y) =
if a < b then a::merge(x,b::y)
else b::merge(a::x,y);
You seem reasonably close. A few hints/remarks:
1) Aesthetically, using nil in one line and [] in others seems odd. Either use all nil or use all []
2) Since the input are lists of lists, in x::y::z, the identifiers x and y would be lists of integers, rather than individual integers. Thus, x<y wouldn't make sense. You can't compare lists of integers using <.
3) Your problem description strongly suggests that the inner-lists are all 1-element lists. Thus you could use the pattern [x]::[y]::z to allow you to compare x and y. In this case, x#y could be replaced by [x,y]
4) If the inner lists are allowed to be of arbitrary size, then your code needs major revision and would probably require a full-fledged sort function to sort the result of concatenating pairs of inner lists. Also, in this case, the single list in the one inner list case should probably be sorted.
5) You have a typo: mergeP isn't mergePass.
On Edit:
If the sublists are each sorted (and the name of the overall function perhaps suggests this) then you need a function called e.g. merge which will take two sorted lists and combine them into a single sorted list. If this is for a class and you have already seen a merge function as an example (perhaps in a discussion of merge-sort) -- just use that. Otherwise you will have to write your own before you write this function. Once you have the merge function, skip the part of comparing x and y and instead have something as simple as:
| mergePass (xs::ys::zss) = (merge xs ys) :: mergePass zss
If the sublists are not merged, then you will need a full-fledged sort in which case you would use something like:
| mergePass (xs::ys::zss) = sort(xs # ys) :: mergePass zss
Given a list, I would like to produce a second list of elements selected from the first one.
For example:
let l1 = [1..4]
let n = [0; 2]
l1.[n]
should return 1 and 3, the first and third element of l1.
Unfortunately, it returns an error:
error FS0001: This expression was expected to have type
int but here has type int list
Now, I wonder, does exist a way to pass an argument n representing a list or, even better, an expression?
F# doesn't offer syntactical support for that sort of indexing. You can ask for a continuous slice of an array like below, but it doesn't cover your exact scenario.
let a = [|1 .. 4|]
let b = a.[0..2]
// returns [|1; 2; 3|]
You can easily write a function for that though:
let slice<'a> (indices: int list) (arr: 'a array) =
[| for idx in indices do yield arr.[idx] |]
slice [0; 2] a
// returns [| 1; 3 |]
I'm leaving proper handling of out-of-bounds access as an exercise ;)
With indexed properties, you should be able to define this for your types: just define a member Item with get(indexes) which accepts a list/array. But standard lists and arrays already have Item defined, and you can't have two at once...
I solved it this way:
List.map (fun index -> l1.[index]) n
It's inefficient for large lists, but works for me.
I was wondering if it is possible to have compile-time check in OCaml to make sure arrays are the correct length. For my problem, I want to verify that two GPU 1-dim vectors are of the same length before doing piecewise vector subtraction.
let init_value = 1
let length = 10_000_000
let x = GpuVector.create length init_value and y = GpuVector.create 9 init_value in
let z = GpuVector.sub v1 v2
In this example I would like it to throw a compile error as x and y are not the same length. As I am a OCaml noob I would like to know how I can achieve this? I am guessing that I will have to use functors or camlp4 (which I have never used before)
You cannot define a type family in OCaml for arrays of length n where n can have arbitrary length. It is however possible to use other mechanisms to ensure that you only GpuVector.sub arrays of compatible lengths.
The easiest mechanism to implement is defining a special module for GpuVector of length 9, and you can generalise the 9 by using functors. Here is an example implementation of a module GpuVectorFixedLength:
module GpuVectorFixedLength =
struct
module type P =
sig
val length : int
end
module type S =
sig
type t
val length : int
val create : int -> t
val sub : t -> t -> t
end
module Make(Parameter:P): S =
struct
type t = GpuVector.t
let length = Parameter.length
let create x = GpuVector.create length x
let sub = GpuVector.sub
end
end
You can use this by saying for instance
module GpuVectorHuge = GpuVectorFixedLength.Make(struct let length = 10_000_000 end)
module GpuVectorTiny = GpuVectorFixedLength.Make(struct let length = 9 end)
let x = GpuVectorHuge.create 1
let y = GpuVectorTiny.create 1
The definition of z is then rejected by the compiler:
let z = GpuVector.sub x y
^
Error: This expression has type GpuVectorHuge.t
but an expression was expected of type int array
We therefore successfully reflected in the type system the property for two arrays of having the same length. You can take advantage of module inclusion to quickly implement a complete GpuVectorFixedLength.Make functor.
The slap library implements such kind of size static checks (for linear algebra).
The overall approach is described this abstract
I want to deal with limits on the integer number line.
I would like to have Pervasives.compare treat RightInfinity > Point x for all x, and the inverse for LeftInfinity.
In the ocaml REPL:
# type open_pt = LeftInfinity | Point of int | RightInfinity
;;
# List.sort Pervasives.compare [LeftInfinity; Point 0; Point 1; RightInfinity]
;;
- : open_pt list = [LeftInfinity; RightInfinity; Point 0; Point 1]
but
# type open_pt = LeftInfinity | Point of int | RightInfinity of unit
;;
# List.sort Pervasives.compare [LeftInfinity; Point 0; Point 1; RightInfinity ()]
;;
- : open_pt list = [LeftInfinity; Point 0; Point 1; RightInfinity ()]
"The perils of polymorphic compare" says
Variants are compared first by their tags, and then, if the tags are equal, descending recursively to the content.
Can one rely on any relationship between the order in which variants appear in a type declaration and the order of the tags?
No, you should not rely on that. You should define your own comparison function. Of course, that means you'll have to lift it through datastructures (to be able to compare, say, lists of open_pt), but that's the safe thing to do when you want a domain-specific comparison function.
Note that extended standard libraries such as Batteries or Core provide auxiliary functions to lift comparisons through all common datastructures, to help you extend your domain-specific comparison to any type containing an open_pt.
Edit: Note that you can rely on that, as the ordering of non-constant constructors is specified in the OCaml/C interface. I don't think that's a good idea, though -- what if you need to put closures inside your functor argument type next time?
fun a(list) =
let
val num = length(hd(list))
fun inner(list) =
if num = length(hd(list)) then
if tl(list) = nil then true
else inner(tl(list))
else false
in
if length(hd(list))-1 = length(tl(list)) then inner(tl(list))
else false
end;
this is ml code and I got this warning and type.
stdIn:6.16 Warning: calling polyEqual
val a = fn : ''a list list -> bool
I don't understand about the warning. why it appear and the type. ''a why it has two '? ''?
what is the difference between 'a list list and ''a list list?
Excerpted from ML Hints:
Warning: calling polyEqual [may occur] whenever you use = to
compare two values with polymorphic type.
For example, fun eq(x,y) = (x = y); will cause this warning to be
generated, because x and y will have polymorphic type ''a. This
is perfectly fine and you may ignore the warning. It is not reporting
any kind of semantic error or type error in your code. The compiler
reports the warning because there can be a slight ineffeciency in how
ML tests whether two values of a polymorphic type are equal. In
particular, to perform the equality test, the run-time system must
first determine what types of values you are currently using and then
determine whether the values are equal. The first part (checking the
run-time types) can make the = test slightly slower than if the
types are known ahead of time (such as when we test 3 = 4 and know
that the = test is being applied to integers). However, that is not
something most users of ML ever need to worry about...
To answer your second question,
why it has two '? ''? what is the difference between 'a list list and
''a list list?
''a is the same as 'a, but requires it to be an equality type. An equality type in SML is a type that can be compared using =. Non-equality types cannot be compared using =. When you create a datatype, you can specify whether it is an equality type or not.
dict=val a =[("a",[1,2]),("b",[2,3])] ;
here is the code which has implementation of look up in dictionary
fun look key [] = []
| look key ((a,b)::xs) = if (key =a ) then b else look key xs ;
which gives output as
test1.sml:8.36 Warning: calling polyEqual
It is because it does not know what are the types which are compared so
the below code says that both are string type .
fun look (key:string) [] = []
| look (key:string) ((a:string,b)::xs) = if (key =a ) then b else look (key:string) xs ;