SML create a list of lists operand mismatch - list

I am trying to create a list of lists meaning my result should be like
thatgraph = [[0,[1,2]],[1,[1,3],[1,4],[1,5]],[2,[3,4],[4,4],[5,5],[5,10]]
The code i use is :
fun pin2graph (pin,thatgraph,i,j,rows,cols,havepizza) =
if (i<rows) andalso (j<cols-1) then
(
pin2graph (pin,thatgraph::((i*cols+j),(getAdjacent (pin,i,j,rows,cols,havepizza))),i,j+1,rows,cols,havepizza)
)
else if (i<rows) then
(
pin2graph (pin,thatgraph::((i*cols+j),(getAdjacent (pin,i,j,rows,cols,havepizza))),i+1,0,rows,cols,havepizza)
)
else thatgraph
The getadjacent function is of type :
val getAdjacent = fn
: char Array2.array * int * int * int * int * 'a -> (int * 'a) list
the 'a is actually a real number so the real type is (int * real) list .
Whatever i have tried i always get an operand and operator mismatch with most common being :
operator domain: _ * _ list
operand: _ * (int * (int * 'Z) list)
Any hint would be greatly appreciated , running out of ideas

Related

Error: This expression has type (int * int) option but an expression was expected of type 'a * 'b

If i put this code to utop line by line, then it works, but if I compile it as programm, then I see error.
module List = Core.Std.List;;
let () =
let shifts = [ (-1, -1); (0, -1) ] in
let first = List.nth shifts 0 in
let (a, b) = first in
Printf.printf "%d %d\n" a b;
;;
And error message:
Error: This expression has type (int * int) option
but an expression was expected of type 'a * 'b
What wrong with types and why it works in utop?
It looks to me like Core.Std.List.nth has the type 'a list -> int -> 'a option in order to handle the case when the int is out of range. The standard library List.nth has the type 'a list -> int -> 'a. It raises an exception for an out-of-range int.
If you're using Core.Std.List in one case but the standard List in the other, this would explain the difference.

How to supply function arguments from a list?

Assume I have a function f that takes n arguments of the same type f: 'a * 'a * ... * 'a -> 'b
Assume I have a list lof n 'a elements,
Does the functor call_function_with_list exist? It would mean this:
call_function_with_list f l = f l[0] l[1] ... l[n-1]
Observe that I am not interested in specifying a particular call_function_with_list for a fixed number n (which could be done quite simply) but I am interested in having a general call_function_with_list that works for all n
You can't (without resorting to the dark magic of the Obj module, that is). Indeed, there are two issues. First OCaml's type system cannot represents something like 'a list -> ('a * 'a * ... * 'a) where ... actually depends on the length of the argument (you could do something like that in Coq for instance). Second, in OCaml an n-uple is not an iterated version of a pair, i.e. a value of type 'a * 'a * 'a is neither a value of type 'a * ('a * 'a) nor of type ('a * ('a * 'a)), so that you cannot build your nuple step by step from the elements of the list.
# let x = (1,2,3);;
val x : int * int * int = (1, 2, 3)
# let y = (1,(2,3));;
val y : int * (int * int) = (1, (2, 3))
# let z = (1,2),3;;
val z : (int * int) * int = ((1, 2), 3)
# x = y;;
Error: This expression has type int * (int * int)
but an expression was expected of type int * int * int
# x = z;;
Error: This expression has type (int * int) * int
but an expression was expected of type int * int * int

Is this a case where I need a functor?

I'm using the Bitstring module in the following code:
let build_data_32 v wid =
let num = wid / 32 in
let v' = Int32.of_int(v) in
let rec aux lst vv w = match w with
0 -> lst
| _ -> (BITSTRING { vv : 32 } ) :: ( aux lst (Int32.succ vv) (w-1)) in
Bitstring.concat ( aux [] v' num ) ;;
Note that when you have BITSTRING { vv : 32 }
that vv is expected to be an Int32 value. I'd like to generalize this function to work with different widths of bitstrings; ie, I'd like to create a build_data_n function where the bitstring would be constructied with BITSTRING { vv : n } .
However, the problem here is that if n is less than 32 then the succ function used above would just be the succ for type int. If it's greater than 32 it would be Int64.succ Same issue above in the line let v' = Int32.of_int(v) in - for values less than 32 it would simply be: let v' = v in , whereas for values greater than 32 it would be: let v' = Int64.of_int(v) in
Is this a case where a functor would come in handy to generalize this function and if so, how would I set that up? (and if there's some other way to do this that doesn't require functors, that would be nice to know as well)
There are a few approaches available. One is to use a functor, similar to the following:
(* The signature a module needs to match for use below *)
module type S = sig
type t
val succ : t -> t
val of_int : int -> t
end
(* The functor *)
module Make(M : S) = struct
(* You could "open M" here if you wanted to save some typing *)
let build_data v =
M.succ (M.of_int v)
end
(* Making modules with the functor *)
module Implementation32 = Make(Int32)
module Implementation64 = Make(Int64)
let foo32 = Implementation32.build_data 12
let foo64 = Implementation64.build_data 12
Another is to wrap your data type in a record:
(* A record to hold the relevant functions *)
type 'a wrapper_t = { x : 'a; succ : 'a -> 'a }
(* Use values of type 'a wrapper_t in *)
let build_data v =
v.succ v.x
(* Helper function to create 'a wrapper_t values *)
let make_int32_wrapper x = { x = Int32.of_int x; succ = Int32.succ }
let make_int64_wrapper x = { x = Int64.of_int x; succ = Int64.succ }
(* Do something with a wrapped int32 *)
let foo32 = build_data (make_int32_wrapper 12)
let foo64 = build_data (make_int64_wrapper 12)
And finally, if you are using OCaml 3.12.0 or later, you can use first class modules:
(* You can use the module type S from the first example here *)
let build_data (type s) m x =
let module M = (val m : S with type t = s) in
M.succ x
let int32_s = (module Int32 : S with type t = Int32.t)
let int64_s = (module Int64 : S with type t = Int64.t)
let foo32 = build_data int32_s 12l
let foo64 = build_data int64_s 12L
Each of these approaches can be mixed and matched. You may also be able to wrap your values in variant types or objects to get a similar result.
With BITSTRING { vv : n }, i.e. using runtime-specified field length, the type of vv cannot depend on n as it is not the compile-time constant anymore, so vv is forced to int64.

unfolding lists in ML

hello everyone I'm trying to write function which can unfold int in the list from any depth, for example if I have following bigList: [12, [34], [11,[1]]] I want to receive
[(1,12),(2,34),(3,11),(4,1)]
first element in tuple is the depth and the second is the number
I wrote this code:
datatype 'a bigList = Empty of unit
| Element of 'a
| List of 'a bigList list;
local
fun unfolder( Empty , n ) = []
| unfolder( (Element l)::ls, n ) = (n, l)::unfolder( ls, n )
| unfolder( (List l)::ls, n) = unfolder( l, n + 1)::unfolder(ls, n)
in
fun flat list = unfolder(list, 1)
end;
every time I receive the following error:
Standard ML of New Jersey v110.71 [built: Thu Sep 17 08:50:14 2009]
- datatype 'a bigList = Element of 'a | Empty of unit | List of 'a bigList list
stdIn:9.5-11.69 Error: data constructor Empty used without argument in pattern
stdIn:11.33-11.69 Error: operator and operand don't agree [tycon mismatch]
operator domain: (int * 'Z) list * (int * 'Z) list list
operand: (int * 'Z) list * (int * 'Z) list
in expression:
unfolder (l,n + 1) :: unfolder (ls,n)
-
thanks in advance for any help
data constructor Empty used without argument in pattern
You defined Empty as Empty of unit, which means you need to use it as Empty (), which is pretty pointless. To use it as just Empty, you need to define it as Empty without the of unit.
unfolder (l,n + 1) :: unfolder (ls,n)
The type of :: is 'a * ['a] -> ['a], which means that the left operand must be a single element and the right operand a list. In the above both operands are a list, so you get a type error.
To concatenate two lists use the # operator, not ::.

how to create a lazy tree in Standard ML

I want to implement a lazy tree in Standard ML with
datatype tr = N of int * unit->tr * unit->tr;
I tried to use
fun form k = N(k,fn()=>form(k+1),fn()=>form(k+3));
as a test of concept, but I get error message saying type mismatch.
What would be the proper way of implementing a lazy tree in ML?
datatype tr = N of int * unit->tr * unit->tr;
This is parsed as
datatype tr = N of (int * unit) -> ( (tr * unit) -> tr)
You want
datatype tr = N of int * (unit->tr) * (unit->tr)