I am often told that using the Lazy module in OCaml, one can do everything you can do in a lazy language such as Haskell. To test this claim, I'm trying to write a function that converts a regular list into a static doubly linked list in ocaml.
type 'a dlist = Dnil | Dnode of 'a dlist * 'a * 'a dlist
Given this type I can create several static doubly linked lists by hand:
let rec l1 = Dnode (Dnil,1,l2)
and l2 = Dnode (l1,2,l3)
and l3 = Dnode (l2,3,Dnil)
but I'd like to write a function of type 'a list -> 'a dlist that given any list builds a static doubly linked list in OCaml. For example given [1;2;3] it should output something equivalent to l1 above.
The algorithm is pretty straightforward to write in Haskell:
data DList a = Dnil | Dnode (DList a) a (DList a)
toDList :: [a] -> DList a
toDList l = go Dnil l
where
go _ [] = Dnil
go h (x:xs) = let r = Dnode h x (go r xs) in r
but I haven't been able to figure out where to place calls to lazy to get this to compile in OCaml.
If you build your linked list in right-to-left order (as for normal lists), then the left element of every node will only be built after that node itself is built. You need to represent this by making the left element lazy, which means "this value will be constructed later" :
type 'a dlist =
| Dnil
| Dnode of 'a dlist Lazy.t * 'a * 'a dlist
Once you have this, construct every node as a lazy value using a recursive definition which passes the lazy (still unconstructed) node to the function call that builds the next node (so that it has access to the previous node). It's actually simpler than it looks :
let dlist_of_list list =
let rec aux prev = function
| [] -> Dnil
| h :: t -> let rec node = lazy (Dnode (prev, h, aux node t)) in
Lazy.force node
in
aux (Lazy.lazy_from_val Dnil) list
You can only build a cyclic immutable strict data structure of a shape that's determined at compile time. I'm not going to define or prove this formally, but intuitively speaking, once the data structure is created, its shape isn't going to change (because it's immutable). So you can't add to a cycle. And if you create any element of the cycle, you need to create all the other elements of the cycle at the same time, because you can't have any dangling pointer.
Ocaml can do what Haskell can do, but you do have to get the Lazy module involved! Unlike Haskell's, ML's data structures are strict unless otherwise specified. A lazy data structure has pieces of type 'a Lazy.t. (ML's typing is more precise than Haskell on that particular issue.) Lazy data structures allow cycles to be built by having provisionally-dangling pointers (whose linked values are automatically created when the pointer is first dereferenced).
type 'a lazy_dlist_value =
| Dnil
| Dnode of 'a lazy_dlist_value * 'a * 'a lazy_dlist_value
and 'a lazy_dlist = 'a lazy_dlist_value Lazy.t
Another common way to have cyclic data structures is to use mutable nodes. (In fact, die-hard proponents of strict programming might see lazy data structures as a special case of mutable data structures that doesn't break referential transparency too much.)
type 'a mutable_dlist_value =
| Dnil
| Dnode of 'a mutable_dlist_value * 'a * 'a mutable_dlist_value
and 'a mutable_dlist = 'a mutable_dlist_value ref
Cyclic data structures are mostly useful when they involve at least one mutable component, one function (closure), or sometimes modules. But there'd be no reason for the compiler to enforce that — cyclic strict immutable first-order data structures are just a special case which can occasionally be useful.
type 'a dlist = Dnil | Dnode of 'a dlist Lazy.t * 'a * 'a dlist Lazy.t
let rec of_list list = match list with
[] -> Dnil
| x :: [] ->
let rec single () = Dnode (lazy (single ()), x, lazy (single ()))
in single ()
| x :: y -> Dnode (
lazy (
of_list (match List.rev list with
[] | _ :: [] -> assert false
| x :: y -> x :: List.rev y
)
),
x,
lazy (
of_list (match list with
[] | _ :: [] -> assert false
| x :: y -> y # x :: []
)
)
)
let middle dlist = match dlist with
Dnil -> raise (Failure "middle")
| Dnode (_, x, _) -> x
let left dlist = match dlist with
Dnil -> raise (Failure "left")
| Dnode (x, _, _) -> Lazy.force x
let right dlist = match dlist with
Dnil -> raise (Failure "right")
| Dnode (_, _, x) -> Lazy.force x
Related
I want to implement the List.assoc function using List.find, this is what I have tried:
let rec assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> try (List.find (fun x -> a = x) lista)
b
with Not_found -> assoc l x;;
but it gives me this error:
This expression has type ('a * 'b) list but an expression was expected of type 'a list
The type variable 'a occurs inside 'a * 'b
I don't know if this is something expected to happen or if I'm doing something wrong. I also tried this as an alternative:
let assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> match List.split lista with
| (l1,l2) -> let ind = find l1 (List.find (fun s -> compare a x = 0))
in List.nth l2 ind;;
where find is a function that returns the index of the element requested:
let rec find lst x =
match lst with
| [] -> raise Not_found
| h :: t -> if x = h then 0 else 1 + find t x;;
with this code the problem is that the function should have type ('a * 'b) list -> 'a -> 'b, but instead it's (('a list -> 'a) * 'b) list -> ('a list -> 'a) -> 'b, so when I try
assoc [(1,a);(2,b);(3,c)] 2;;
I get:
This expression has type int but an expression was expected of type
'a list -> 'a (refering to the first element of the pair inside the list)
I don't understand why I don't get the expected function type.
First off, a quick suggestion on making your assoc function more idiomatic OCaml: have it take the list as the last argument.
Secondly, why are you attempting to implement this in terms of find? It's much easier without.
let rec assoc x lista =
match lista with
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
Something like this is simpler and substantially more efficient with the way lists work in OCaml.
Having the list as the last argument, even means we can write this more tersely.
let rec assoc x =
function
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
As to your question, OCaml infers the types of functions from how they're used.
find l1 (List.find (fun s -> compare a x = 0))
We know l1 is an int list. So we must be trying to find it in an int list list. So:
List.find (fun s -> compare a x = 0)
Must return an int list list. It's a mess. Try rethinking your function and you'll end up with something much easier to reason about.
I am trying to write a function that filters positive integers from a list of list of integers, returning a list of only negative integers.
For example, if I have a list of list such as [[-1; 1]; [1]; [-1;-1]] it would return [[-1]; []; [-1;-1]].
I tried to use filter and transform functions, which was in my textbook.
let rec transform (f:'a -> 'b) (l:'a list) : 'b list =
begin match l with
| [] -> []
| x::tl -> (f x)::(transform f tl)
end
and for filter, I had previously written:
let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list =
begin match l with
| [] -> []
| x :: tl -> if pred x then x :: (filter pred tl) else filter pred tl
end
So, using these, I wrote
let filter_negatives (l: int list list) : int list list =
transform (fun l -> (filter(fun i -> i<0)) + l) [] l
but I'm still having trouble fully understanding anonymous functions, and I'm getting error messages which I don't know what to make of.
This function has type ('a -> 'b) -> 'a list -> 'b list
It is applied to too many arguments; maybe you forgot a `;'.
(For what it's worth this transform function is more commonly called map.)
The error message is telling you a simple, true fact. The transform function takes two arguments: a function and a list. You're giving it 3 arguments. So something must be wrong.
The transformation you want to happen to each element of the list is a filtering. So, if you remove the + (which really doesn't make any sense) from your transforming function you have something very close to what you want.
Possibly you just need to remove the [] from the arguments of transform. It's not clear (to me) why it's there.
I want to print a list with different element in it (for educational purpose)
I have read a tutorial that explain how to store different type in list.
type _ list =
[] : unit list
| ( :: ) : 'b * 'a list -> ('b ->'a) list;;
1 :: "e" :: 'r' :: [];; (* this is allowed *)
how I can do something like this pseudo-code:
match typeof(my_expr) with
int -> print_int
| string -> print_string
we will have "1,e,r" printed.
Some solutions i have searched
Change my type in text and printing it
Use a different type definition maybe ('a, 'b) list ?
I ask this because the OCaml toplevel know the type of every variable and show always the type in the right format: can I call this printer ?
Is there a solution only for toplevel that we can install with the #install_printer ?
I know that compiler discard type's info after the type checking pass.
The printer of the toplevel should work fine:
[1; "one"; 1.];;
- : (int -> string -> float -> unit) list =
(::) (1, (::) ("one", (::) (1., [])))
(The unoptimal printing is an unfortunate consequence of ensuring that values printed by the toplevel can be copy-pasted back to the top-level and yields the same value)
But this is only possible outside of the language itself: the toplevel printers can inspect the typing environment which is purposefully not possible in the language itself. Indeed functions like typeof would break parametricity. There is thus no universal printer function in OCaml (without looking at the internal memory representation) and no universal heterogeneous list printer.
If you want to print an heterogeneous list, there are three possible paths:
print a specific type of the heterogeneous list
let print_concrete ppf (x::y::z::rest) = Format.fprintf ppf "%f %f %f" x y z
(Contrary to appearance, this function is total: its type makes it impossible to use on lists with fewer than three elements)
Use heterogeneous lists that always pack a printing function along its main value
type 'a printer = Format.formatter -> 'a -> unit
type _ showable_list =
| [] : unit showable_list
| (::):
('a * 'a printer) * 'b showable_list
-> ('a -> 'b) showable_list
let rec print: type a. a showable_list printer =
fun ppf l -> match l with
| [] -> ()
| (a,printer) :: rest -> Format.fprintf ppf "%a# %a" printer a print rest
provide a matching heterogeneous list of printing functions
type 'a plist =
| []: unit plist
| (::): 'a printer * 'b plist -> ('a -> 'b) plist
let rec print: type l. l plist -> l list printer = fun printers ppf values ->
match printers, values with
| [], [] -> ()
| p :: prest, a :: rest -> Format.fprintf ppf "%a# %a" p a (print prest) rest
The fact that you often need to specialize the heterogeneous list type may make it worthwhile to introduce a functor for generating them:
module Hlist(Specialization: sig type 'a t end) = struct
open Specialization
type 'a list =
| []: unit list
| (::): 'a t * 'b list -> ('a -> 'b) list
end
then the previous specialized type can be constructed with
module Showable_list = Hlist(struct type 'a t = 'a * 'a printer end)
module Printer_list = Hlist (struct type 'a t = 'a printer end)
let rec (l:int list) f int list =
match l with
| [] -> []
| hd::tl -> 2+tl
I want to know is hd the first element and then tl is the second element because when i do this I keep getting an error, if tl is not the second element how would i access the second element an in depth explanation of hd::tl would be highly appreciated thank you
No tl is not the second element, it is the rest of the list and it has type 'a list. Here hd and tl are just variable names that you choose to bind to the first element of a list, and to the rest of the list (i.e., to a list that contains all elements except the first one). You can choose other names, e.g., fst::rest. Getting the second element, in that case would be as easy as fst::snd::rest (or x::y::rest - again the name doesn't matter).
What you're trying to use is called pattern matching. It is a feature of some languages, that provides a mechanism to easily deconstruct compound data structures. The idea is that if you're deconstructing data structures the same way as you're constructing them, e.g,
let xs = [1;2;3;4]
and here is the deconstructing
let [x1;x2;x3;x4] = xs
In fact, [x;y;...;z] is a syntactic sugar for a more basic syntax x :: y:: ... :: z :: [], so another way to construct the [1;2;3;4] list is to use the following construct: 1::2::3::4::[]. The same works in the opposite direction, e.g.,
let x1::x2::x3::x4::[] = xs
Now we are ready to the next step, what if the structure on the right doesn't match the structure on the left, e.g.,
let [x;y;z] = [1;2]
or
let x::y::z::[] = 1::2::[]
In that case, the matching will fail. In our case in runtime. To prevent this, and to allow programmers to handle all possible configuration of their data structures OCaml provides the match construct in which you specify multiple variants of the value structure, and the first one that matches is chosen, e.g.,
let orcish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
The function above anticipates only lists that have up to three elements (because Orcs can't count beyond three). But we can. For this we will use the following feature -- if the last element of the list pattern is not [] (that is matches only and only with the empty list, and designates the end-of-list), but anything else (i.e., a variable), then this variable will be bound to all elements, e.g.,
let rec elvish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
| x :: y :: z :: leftovers -> 3 + elvish_length leftovers
So now, we anticipate all possible list patterns. However, the function is now overcomplicated (because Elves are complicating). Now, let's finally derive a normal, human readable, length function,
let rec length xs = match xs with
| [] -> 0
| x :: xs -> 1 + length xs
As an exercise, try to prove to yourself that this function anticipates all possible lists.
:: is read cons and is an infix version of List.cons. In a functional language like Ocaml, list is a linked list where i.e.[e1; e2; e3; e4] can be reduced to something like this:
cons(::)
/ \
e1 cons(::)
/ \
e2 cons(::)
/ \
e3 cons(::)
/ \
e4 [ ]
Basically, any list can be reduced to a tree of recursive cons expressions, which makes recursion so useful in Ocaml or similar functional languages. At each level, you can reduce a list to its head and its tail, where tail is the list minus its head and can be reduced further until last :: []. So with the above example, you can recursively reduce the list until you find the last element by pattern-matching:
let find_last li =
match li with
| [] -> None (* no element *)
| [last] -> Some last (* found last *)
| head :: tail -> find_last tail (* keep finding *)
;;
Note that [last] can be replaced with last::[] and head::tail with List.cons head tail. What is important is at any point a list can always be reduced to head :: tail, where head is the first element and tail is the list without head.
Pattern-matching is useful in matching the "shape" or state of the reducing list.
I'm trying to make a function that take some list of type 'a list, where 'a could be of type 'b list, and 'b could be of type 'c list and so forth. it should revert every list in the list so that if 'a is a list then 'a should also be reverted and so forth.
let RevAll xs =
let rec rev acc = function
| (_::_)::__ as M -> rev ((rev List.Empty List.head M)::acc) (List.tail M)
| x::xs -> rev (x::acc) xs
| [] -> acc
rev List.Empty xs
Vs' compiler can't determent the types so it don't work. My question is as follow. Is there a way to make a function in F# that take an n-dimensional list and revert every dimension in that list without specifying the dimension?