Let's import our ListStack module from before.
module ListStack = struct
type 'a stack = 'a list
let empty = []
let push x s = x :: s
let peek = function
| [] -> failwith "Empty"
| x :: _ -> x
let pop = function
| [] -> failwith "Empty"
| _ :: s -> s
end
module ListStack :
sig
type 'a stack = 'a list
val empty : 'a list
val push : 'a -> 'a list -> 'a list
val peek : 'a list -> 'a
val pop : 'a list -> 'a list
end
Now, let's create a ListStack.
let x = ListStack.peek (ListStack.push 42 ListStack.empty)
val x : int = 42
That's quite verbose. There should be a way to simplify that.
let x = ListStack.(peek (push 42 empty))
val x : int = 42
Inside these parentheses, ListStack will remain in scope.
let x = ListStack.(empty |> push 42 |> peek)
val x : int = 42
The pipeline operator makes things prettier 😊
We can also use a local open
let x =
let open ListStack in
empty |> push 42 |> peek
val x : int = 42
This puts ListStack in scope for the entire let statement
A global open is another option; however, it's discouraged.
open ListStack
empty |> push 42 |> peek
- : int = 42
It's best to be very sparing in your use of global opens. One of the few time we do this is opening OUnit, but sometimes you might make one that we know is safe to open, and that's okay too, but generally, opening data structures is bad.