Using Poly/ML, I wanted to write a function to construct an n*n identity matrix using Array of Arrays.
I wrote:
fun equiv x y = if x = y then 1 else 0;
fun idmatrix n = Array.tabulate(n, fn i => (Array.tabulate(n, equiv i)));
and it compiled successfully, giving
> val equiv = fn: ''a -> ''a -> int
> val idmatrix = fn: int -> int array array
But when I called idmatrix
idmatrix 2;
for a test, the output of the compiler was
> Exception- Cast "toAddress" raised
Can anybody explain why the exception was raised, please?
Thank you very much!
Your code works fine for me. Looking at the code that raises the exception, perhaps it's a 32/64-bit address problem? Is your Poly/ML compiled for the right architecture?
Poly/ML:
$ poly
Poly/ML 5.2 Release
> fun equiv x y = if x = y then 1 else 0;
val equiv = fn : ''a -> ''a -> int
> fun idmatrix n = Array.tabulate(n, fn i => (Array.tabulate(n, equiv i)));
val idmatrix = fn : int -> int Array.array Array.array
> idmatrix 3;
val it = fromList[fromList[1, 0, 0], fromList[0, 1, 0], fromList[0, 0, 1]]
: int Array.array Array.array
Moscow ML:
$ mosml
Moscow ML version 2.10
Enter `quit();' to quit.
- fun equiv x y = if x = y then 1 else 0;
> val ''a equiv = fn : ''a -> ''a -> int
- fun idmatrix n = Array.tabulate(n, fn i => (Array.tabulate(n, equiv i)));
> val idmatrix = fn : int -> int array array
- idmatrix 3;
> val it = <array> : int array array
And SML/NJ:
$ sml
Standard ML of New Jersey v110.76 [built: Sun Jun 29 03:29:51 2014]
- fun equiv x y = if x = y then 1 else 0;
stdIn:1.23 Warning: calling polyEqual
val equiv = fn : ''a -> ''a -> int
- fun idmatrix n = Array.tabulate(n, fn i => (Array.tabulate(n, equiv i)));
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val idmatrix = fn : int -> int array array
- idmatrix 3;
val it = [|[|1,0,0|],[|0,1,0|],[|0,0,1|]|] : int array array
Related
This question already has answers here:
transpose of a list of lists
(3 answers)
Closed 12 months ago.
I'd like to write a function in OCaml, using only recursivity that can transform any list of list that look like: [[a1;...;an];[b1;...bn];...;[z1;...;zn]] into [[a1;b1;...;z1];...;[an;...;zn]] what I've done so far is quite complex, I insert element by element reconstructing a new list every time ... and I'm sure there is a simpler way ...
My code so far:
let inserer l e i =
let rec aux l e i j =
match l with
| [] -> failwith "erreur position inexistante"
| t::q when j = i ->
if List.length t = 0 then
[e]::q
else
let t1 = List.hd t in
let q1 = List.tl t in
let l1 = t1::e::q1 in
l1::q
| t::q -> t::(aux q e i (j+1))
in
aux l e i 0
let inserer_liste b m =
let rec aux b m i =
match b with
| [] -> m
| t::q ->
let tmp = inserer m t i in
aux q tmp (i+1)
in
aux b m 0
let transform u n =
let rec aux u m =
match u with
| []-> m
| b::q ->
let tmp = inserer_liste b m in
aux q tmp
in
aux u (List.init n (fun _ -> []))
let u = [[1;2;3]; [4;5;6]; [7;8;9]]
let l = transform u 3
I have a feeling that this transformation is way more natural if you transform an array of lists into a lists of arrays. You can transform into a list of lists afterwards.
let rec f a =
match a.(0) with
| [] -> []
| _ :: _ ->
let hd = Array.map List.hd a in
for i = 0 to Array.length a - 1 do
a.(i) <- List.tl a.(i)
done ;
hd :: (f a)
This consumes the input array, which can be solved by shadowing f in the following way :
let f a = f (Array.copy a)
let f_list l = List.map Array.to_list (f (Array.of_list l))
You could also reallocate a new array at each recursive call, but that would be slower, without any upside except maybe a bit nicer code.
f_list is more elegant this way :
let f_list l =
l |> Array.of_list |> f |> List.map Array.to_list
There is no error handling in my code : it assumes all list have the same length, but it should be to hard to add it.
Is there a simple way... Not that I know of but that doesn't say much.
Here's something I tried.
let lol =
[
[ 1; 2; 3; 4; ];
[ 5; 6; 7; 8; ];
[ 9; 10; 11; 12; ];
]
let ans =
List.fold_left
(
fun a e ->
match a with
| [] -> List.fold_right (fun e a -> [e]::a) e a
| _ -> List.fold_right2 (fun b c acc -> (c # [b])::acc) e a []
)
[]
lol
let () =
List.iter
(
fun l ->
List.iter (fun x -> Printf.printf "%d " x) l;
print_newline()
)
ans
After some thought I cam up with this
let lol =
[
[11; 12; 13; 14; 15; 16; 17; 18; 19; ];
[21; 22; 23; 24; 25; 26; 27; 28; 29; ];
[31; 32; 33; 34; 35; 36; 37; 38; 39; ];
[41; 42; 43; 44; 45; 46; 47; 48; 49; ];
]
let rec transpose ll =
match ll with
| [] -> []
| l -> (List.map List.hd l)::
(
try
transpose (List.map List.tl l)
with
| _ -> []
)
let ans = transpose lol
let () =
List.iter
(
fun l -> List.iter (fun x -> Printf.printf "%d " x) l; print_newline()
)
ans
Is it best to always eta-expand as a fool-proof rule of thumb in OCaml ?
type 'x recordx = { x : int }
type 'y recordy = { y : int }
let rec ok : type n a. n recordx -> a recordy -> int =
fun algebrah x -> ok algebrah x
let rec ok : type a. a recordy -> int =
fun x ->
let go : type b. b recordy -> int = ok in
go x
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = fun y -> ok x y in
go y
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go = ok x in
go y
(* This definition has type
'b recordy -> int which is less general than
'b0. 'b0 recordy -> int
*)
let rec ko : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = ko x in
go y
The relaxed value restriction classifies the eta-expanded form fun y -> f x y as a value that can thus be generalized by let bindings, contrarily to the non-value f y. See https://ocaml.org/manual/polymorphism.html#s%3Aweak-polymorphism .
Moreover, in a eager language like OCaml, eta-expansion does change the semantics of functions. Consider
let print x =
Format.printf "x=%s#." x;
fun y -> Format.printf "y=%s#."
and
let print1 = print "x"
let print2 y = print "x" y
Thus, eta-expansion is a semantic-changing transformation rather than a "foolproof" transformation.
I'm currently studying SML and I'm having a hard time understanding the code below
fun good_max (xs : int list) =
if null xs
then 0
else if null (tl xs)
then hd xs
else
(* for style, could also use a let-binding for (hd xs) *)
let val tl_ans = good_max(tl xs)
in
if hd xs > tl_ans
then hd xs
else tl_ans
end
hd xs is of type int and tl_ans, I think is of type list.
Why does this code work? How does the system evaluate the recursion?
It would be great if you could use xs = [3, 4, 5] to show me how this works.
Let me first rewrite this code to an equivalent but more readable version:
fun max(x,y) = if x > y then x else y
fun goodMax(nil) = 0
| goodMax(x::nil) = x
| goodMax(x::xs) = let val y = goodMax(xs) in max(x,y) end
Now we can consider how evaluation of goodMax([3,4,5]) proceeds: conceptually, it will be reduced to an answer by repeatedly substituting the respective branch of the function definition(s):
goodMax([3,4,5])
= goodMax(3::[4,5])
= let val y = goodMax([4,5]) in max(3, y) end
= let val y = goodMax(4::[5]) in max(3, y) end
= let val y = (let val y' = goodMax([5]) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = goodMax(5::nil) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = 5 in max(4, y') end) in max(3, y) end
= let val y = max(4, 5) in max(3, y) end
= let val y = (if 4 > 5 then 4 else 5) in max(3, y) end
= let val y = 5 in max(3, y) end
= max(3, 5)
= if 3 > 5 then 3 else 5
= 5
I have renamed the y in the inner invocation to y' for clarity.
I have a homework where i need to write 2 communication servers, one which generates natural numbers and the other which prints them. the generating server will be sending to the printing server. The servers should communicate over the shared channel chan.The main function should spawn a thread for each server.
`
val sender = fn : int -> unit
val receiver = fn : unit -> 'a
val main = fn : unit -> unit
`
And so far this is code i have written:
`
datatype 'a inflist = NIL
| CONS of 'a * (unit -> 'a inflist);
fun HD (CONS(a,b)) = a
| HD NIL = raise Subscript;
fun TL (CONS(a,b)) = b()
| TL NIL = raise Subscript;
fun NULL NIL = true
| NULL _ = false;
fun TAKE(xs, 0) = []
| TAKE(NIL, n) = raise Subscript
| TAKE(CONS(x,xf), n) = x::TAKE(xf(), n-1);
fun FROMN n = CONS (n,fn () => FROMN (n+1));
val natnumber = FROMN 0;
fun printGenList f (h::t) = (f h; printGenList f t);
fun printList l = printGenList (fn(e) => print(Int.toString(e)^" ")) l;
fun printPairList l = printGenList (fn(e,f) => print("("^Int.toString(e)^", "^Int.toString(f)^") ")) l;
CM.make "$cml/cml.cm";
open CML;
val chan: int chan = channel();
fun gen ch () = send (ch, printList(TAKE(natnumber,101)));
fun printnat ch () = recv (ch);
fun main () =
let
val ch = channel() :int chan ;
val _ = spawn (gen ch);
val _ = spawn (printnat ch);
in
()
end;
`
But i am not getting the output. Am i going wrong in my syntax or the logic?
I am new to SML and Concurrent ML. Please help me.
Why are you using a infinite list? There are simpler ways to implement this.
The idea is to walk over multiple dimensions, each one defined as a range
(* lower_bound, upper_bound, number_of_steps *)
type range = real * real * int
so functions like fun foo y x or fun foo z y x could be applied to the whole square XY or cube XY*Z.
SML/NJ doesn't like my implementation below :
test2.sml:7.5-22.6 Error: right-hand-side of clause doesn't agree with function result type [circularity]
expression: (real -> 'Z) -> unit
result type: 'Z -> 'Y
in declaration:
walk = (fn arg => (fn <pat> => <exp>))
Here's the code :
fun walk [] _ = ()
| walk (r::rs) f =
let
val (k0, k1, n) = r
val delta = k1 - k0
val step = delta / real n
fun loop 0 _ = ()
| loop i k =
let in
walk rs (f k) ; (* Note (f k) "eats" the first argument.
I guess SML doesn't like having the
type of walk change in the middle of its
definition *)
loop (i - 1) (k + step)
end
in
loop n k0
end
fun do2D y x = (* ... *) ()
fun do3D z y x = (* ... *) ()
val x_axis = (0.0, 1.0, 10)
val y_axis = (0.0, 1.0, 10)
val z_axis = (0.0, 1.0, 10)
val _ = walk [y_axis, x_axis] do2D
val _ = walk [z_axis, y_axis, x_axis] do3D
Is this kind of construct even possible ?
Any pointer welcomed.
Is walk expressible in ML's type system?
val walk : range list -> (real -> real -> unit) -> unit
val walk : range list -> (real -> real -> real -> unit) -> unit
The same one value cannot possibly exist with both those types in ML.
We can easily generate values for each of the desired types, though.
type range = real * real * int
signature WALK =
sig
type apply
val walk : range list -> apply -> unit
end
structure Walk0 : WALK =
struct
type apply = unit
fun walk _ _ = ()
end
functor WALKF (Walk : WALK) : WALK =
struct
type apply = real -> Walk.apply
fun walk ((low, high, steps)::rs) f =
let fun loop i =
if i > steps then () else
let val x = low + (high - low) * real i / real steps
in (Walk.walk rs (f x); loop (i + 1)) end
in loop 0 end
end
struture Walk1 = WALKF(Walk0)
struture Walk2 = WALKF(Walk1)
struture Walk3 = WALKF(Walk2)
With this, the following values exist with the desired types.
val Walk0.walk : range list -> unit -> unit
val Walk1.walk : range list -> (real -> unit) -> unit
val Walk2.walk : range list -> (real -> real -> unit) -> unit
val Walk3.walk : range list -> (real -> real -> real -> unit) -> unit
Then you only need to write
val _ = Walk2.walk [y_axis, x_axis] do2D
val _ = Walk3.walk [z_axis, y_axis, x_axis] do3D
To use the same walk for every dimensionality, you need it to use the same type for every dimensionality.
fun walk nil f = f nil
| walk ((low, high, steps)::rs) f =
let fun loop i =
if i > steps then () else
let val x = low + (high - low) * real i / real steps
in (walk rs (fn xs -> f (x::xs)); loop (i + 1)) end
in loop 0 end
Because the type is changed to
val walk : range list -> (real list -> unit) -> unit
your usage also has to change to
fun do2D [y,x] = (* ... *) ()
fun do3D [z,y,x] = (* ... *) ()
fun walk lst f = let
fun aux rev_prefix [] = f (rev rev_prefix)
| aux rev_prefix (r::rs) = let
val (k0, k1, n) = r
val delta = k1 - k0
val step = delta / real n
fun loop 0 _ = ()
| loop i k = (
aux (k+step :: rev_prefix) rs;
loop (i - 1) (k + step)
)
in
loop n k0
end
in
aux [] lst
end
fun do2D [x,y] = print (Real.toString x ^ "\t" ^
Real.toString y ^ "\n")
fun do3D [x,y,z] = print (Real.toString x ^ "\t" ^
Real.toString y ^ "\t" ^
Real.toString z ^ "\n")
val x_axis = (0.0, 1.0, 10)
val y_axis = (0.0, 1.0, 10)
val z_axis = (0.0, 1.0, 10)
val () = walk [y_axis, x_axis] do2D
val () = walk [z_axis, y_axis, x_axis] do3D
Found this implementation for variable number of arguments. Not sure it applies but it looks quite ugly.