Type declaration with and - functional-programming

What is benefit of type declaration:
type xxx
and yyy
over
type xxx
type yyy
To give it semantic that one depends on another?
I'm using OcamlWin 4.0 and the code is from C:\OCaml\lib\hashtbl.ml
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
and ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
it compiles. When I change the and to type
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
type ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
compiles as well.

The and keyword is often used when defining mutually recursive declarations
Given your example
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
type ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
would give an Error: Unbound type constructor bucketlist on line 3, characters 20-39. However changing the second type with an and will remove the error.
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
and ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
I can't come up with a reason why it would compile for you in both cases, however if you were using the interpreter and you forget to close it down, then it will have old bindings in its environment.
That is, if you have first evaluated you code with the and keyword then you can keep re-evaluating the code without as bucketlist have already been defined in the invironment.

The and keyword is needed to express mutually recursive definitions. For example,
type t = A | B of u
and u = C | D of t
would no longer compile if you were to replace and with type. In your example, its use is redundant, though.

Related

Syntax for a function with (’a * ’b) list → (’b * ’a) list [duplicate]

This question already has an answer here:
Swap pairs of elements in a list using pattern matching
(1 answer)
Closed 5 years ago.
I am trying to write a function to swap a pair of tuples inside of a list like this:
- pairSwap [(1, 2), (3, 4), (5, 6);
[(2,1),(4,3),(6,5)]
I am having a hard time figuring out what I am doing wrong with my syntax while declaring the function. This is what I have so far:
fun pairSwap ((a : 'a, b: 'a) list) : (('a, 'a) list) =
...
;
Where am I going wrong?
Edit:
Solution
fun pairSwap (t : ('a * 'a) list) : ('a * 'a) list =
if null t
then []
else
let
val v = hd t
in
(#2 v, #1 v)::pairSwap (tl t)
end
;
Since you have provided a solution in the meantime, here is some feedback on it:
You don't really need the type annotations. You can let type inference do the work.
fun pairSwap t = ...
You can use null, hd and tl, but consider pattern matching:
fun pairSwap [] = []
| pairSwap ((x,y)::ps) = (y,x)::pairSwap ps
This also makes the let-expression redundant.
As Matt points out, the type for this function is ('a × 'b) list → ('b × 'a) list, which means you can also swap pairs where the left side has a different type ('a) than the right side ('b), e.g.:
- pairSwap [("hello",42),("world",43)];
val it = [(42,"hello"),(43,"world")] : (int * string) list
You need to pull the variable out of the pair type annotation:
fun pairSwap (arg : ('a * 'b) list) : ('b * 'a) list = ...;
Note that I've also changed it from what you had to what the title requested: ('a * 'a) list -> ('a * 'a) list to ('a * 'b) list -> ('b * 'a) list

How to map both keys and values of a mapping?

I need to define a function which maps keys and values of a finite map into a set of key-value pairs:
theory Test
imports Main "~~/src/HOL/Library/Finite_Map"
begin
definition denorm :: "('a, 'b) fmap ⇒ ('a × 'b) fset" where
"denorm m ≡ "
end
The problem is that I can't define this function by recursion, because fmap isn't an inductive data type and it doesn't have any constructors.
I guess that fmap is represented as a list of pairs internally. Is it possible to convert fmap to the list? I need an inverse of fmap_of_list function.
One possible way is to compose image, domain, and lookup: the expression
λ m. (λ k. (k, the (fmlookup m k))) |`| fmdom m
has the desired type
('a, 'b) fmap ⇒ ('a × 'b) fset
and should compute the desired set for a map m.
This function is already there:
fset_of_fmap :: "('a, 'b) fmap ⇒ ('a × 'b) fset"

SML: Rigorous Way To Parenthesize Function Type

I'm having a bit of difficulty figuring out how to parenthesize a function (when it's legal to add parentheses around certain parts to make the meaning clearer).
For instance, foldl is defined as having type:
foldl : ('a * 'b -> 'b) -> b -> 'a list -> 'b
Now, if I look at foldl's definition, I see:
fun foldl g z [] = z
| foldl g z (x::L) = foldl g (g(x,z)) L;
Based on this, I usually just mentally map g to ('a * 'b -> 'b), z to be of type 'b, and pattern-matching takes care of the list of type 'a list. Finally, the return type is 'b.
However, I thought -> right associates, so wouldn't it be most natural to start by saying "OK, add parentheses like so:
foldl : ('a * 'b -> 'b) -> 'b -> ('a list -> 'b)
What's wrong with this line of thought / what am I misunderstanding about how to add parentheses?
There's nothing wrong with it, it's just redundant.
('a * 'b -> 'b) -> 'b -> ('a list -> 'b), ('a * 'b -> 'b) -> ('b -> ('a list -> 'b)) and ('a * 'b -> 'b) -> 'b -> 'a list -> 'b are all equivalent because -> is right associative. So we usually write the version with the least parentheses (just like one usually writes 3 - 2 - 1 rather than the equivalent (3 - 2) - 1).

How can I create a union type for a tree, where it takes 'a type of key and 'b type of value in OCaml?

I wish to create a bst (binary search tree) union type.
It is either leaf or node. For node, it takes 'a key and 'b value.
I did this:
type 'a*'b bst =
| Node of 'a * 'b * ('a*'b) bst * ('a*'b) bst
| Leaf;;
but it doesn't work
How should I do it?
The syntax for multi-parameter polymorphic types is the following:
type ('a, 'b) bst =
| Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst
| Leaf;;
The syntax you are looking for is:
# type ('a, 'b) bst =
| Node of 'a * 'b * ('a,'b) bst * ('a,'b) bst
| Leaf;;
type ('a, 'b) bst = Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst | Leaf
In addition, you may get into trouble because 'a needs a comparison operator. This is why in the standard library, the Map and Set modules are implemented as functors, so that it is possible to specify the comparison ordering.
If you decide to go along the 'a polymorphism way, you'll have to use the "magical" default comparison operator compare.
The problem is different in F#, because there are ways to attach a comparison operator to a type.

SML/NJ - the "fun act(f,x) = f(x) ;" signature

Declare on the follow function -
fun act(f,x) = f(x);
Makes the signature -
val act = fn : ('a -> 'b) * 'a -> 'b
What does ('a -> 'b) * 'a -> 'b means ?
It means that act is a function that takes a pair (2-tuple)
('a -> 'b) * 'a
where the first element is a function from 'a to 'b, and the second is a thing of type 'a.
It returns a thing of type 'b.

Resources