Recursive types in OCaml? - recursion

Hi this is my first time posting on Stack Overflow and I've run into a problem while trying to construct a type in OCaml
I'm trying to construct a type tree that has nodes/leafs/etc. This is what I have so far.
type ('a, 'b) tree = Empty | Leaf of 'b | Node of ('a * tree) | ....
My node is supposed to be a type that contains the its name and another tree as a tuple. But when I tried to compile this it said tree required two arguments. So I tried:
type ('a, 'b) tree = Empty | Leaf of 'b | Node of ('a * tree ('a*'b))
and I was still getting an error. Anything that you notice I was doing wrong? Thanks!

type ('a, 'b) tree = Empty | Leaf of 'b | Node of 'a * ('a, 'b) tree
You probably want your Nodes two have more than one child, though
type ('a, 'b) tree = Empty | Leaf of 'b | Node of ('a, 'b) tree * 'a * ('a, 'b) tree
PS : Beware than in a type declaration, Foo of bar * baz and Foo of (bar * baz) are not the same : the first is a constructor Foo with two fields, the second has only one field, which is of type (bar * baz).

Related

Is there a way to add syntax for a custom datatype in Isabelle?

So I have two custom datatypes:
datatype ('a, 't) action = ACTION (name: "'a") (args: "'t list") ("⌈_ _⌋")
and
datatype ('a, 't) multiaction = MULTIACTION "('a, 't) action multiset" ("⟨(_)⟩")
Both of them work with their given notations, however whenever I want to use these data structures in their pretty-printed format, it looks a little redundant. For example:
value "⟨{#⌈a b⌋, ⌈c d⌋#}⟩"
What I'd like to do is have the above typed without the multiset brackets, so that it looks like this:
value "⟨⌈a b⌋, ⌈c d⌋⟩"
What I've tried is using syntax:
syntax
"_maction" :: "args ⇒ ('a, 't) multiaction" ("⟨_⟩" [0] 60)
translations
"⟨x⟩" == "CONST MULTIACTION {#x#}"
But when I try it out with some datatypes:
value "⟨⌈''x'' [1,2,3::int]⌋⟩"
But I get a wellsortedness error, which I have no idea why it occurs. Can I please have some help with this?
Thanks in advance!
Perhaps, you are looking to lift the multiset syntax to multiaction? In this case, you may also wish to lift the relevant definitions for the multiset (as noted in the comments, ideally, you will wish to use the datatype/lift_definition infrastructure for this):
datatype ('a, 't) action = ACTION (name: "'a") (args: "'t list") ("⌈_ _⌋")
datatype ('a, 't) multiaction = MULTIACTION "('a, 't) action multiset"
(*this should not be lifted manually: use the integration of
the datatype and lifting infrastructure*)
fun add_multiaction ::
"('a, 'b) action ⇒ ('a, 'b) multiaction ⇒ ('a, 'b) multiaction"
where "add_multiaction x (MULTIACTION xs) = MULTIACTION (add_mset x xs)"
abbreviation MAempty :: "('a, 't) multiaction" ("⟨#⟩") where
"MAempty ≡ MULTIACTION {#}"
syntax
"_multiaction" :: "args ⇒ ('a, 't) multiaction" ("⟨(_)⟩")
translations
"⟨x, xs⟩" == "CONST add_multiaction x ⟨xs⟩"
"⟨x⟩" == "CONST add_multiaction x ⟨#⟩"
value "⟨⌈''x'' [1,2,3::int]⌋, ⌈''x'' [1,2,3::int]⌋⟩"
I have to admit I am not entirely certain if I fully understood what exactly you are trying to achieve: I am providing the first idea that came to my mind based on not-very-thorough understanding of the question.
Isabelle version: Isabelle2021-RC6

What is the main symbol in Isabelle's set operator (‘) :: ('a => 'b) => 'a set => 'b set?

I was wondering what is the symbol ‘ in the Isabelle tutorial main.pdf below (under the section "Set")?
(‘) :: ('a => 'b) => 'a set => 'b set
By looking into the symbols tab, the closest in shape I could find is \<acute> under the "Unsorted" category. I tried to evaluate the following expression, but it doesn't parse:
value "´ (λ(n::nat). n+1) {1,2}"
value "(λ(n::nat). n+1) ´ {1,2}"
Can anyone help to explain the usage here and what it does?
I believe that the symbol that you are looking for is `, not ‘ or ´. The symbol ` is an infix notation for the constant image that is defined in theory Set.thy in the main library of Isabelle/HOL. Hopefully, the name of the constant is self-explanatory. For completeness, I restate the definition in this answer:
definition image :: "('a ⇒ 'b) ⇒ 'a set ⇒ 'b set" (infixr "`" 90)
where "f ` A = {y. ∃x∈A. y = f x}"
Thence,
value "(λ(n::nat). n+1) ` {1,2}"
evaluates to "{2, 3}" :: "nat set", as expected.

Can I annotate the complete type of a `fun` declaration?

In a learning environment, what are my options to provide type signatures for functions?
Standard ML doesn't have top-level type signatures like Haskell. Here are the alternatives I have considered:
Module signatures, which require either a separate signature file, or the type signature being defined in a separate block inside the same file as the module itself. This requires the use of modules, and in any production system that would be a sane choice.
Modules may seem a little verbose in a stub file when the alternative is a single function definition. They both introduce the concept of modules, perhaps a bit early,
Using val and val rec I can have the complete type signature in one line:
val incr : int -> int =
fn i => i + 1
val rec map : ('a -> 'b) -> 'a list -> 'b list =
fn f => fn xs => case xs of
[] => []
| x::ys => f x :: map f ys
Can I have this and also use fun?
If this is possible, I can't seem to get the syntax right.
Currently the solution is to embed the argument types and the result type as such:
fun map (f : 'a -> 'b) (xs : 'a list) : 'b list =
raise Fail "'map' is not implemented"
But I have experienced that this syntax gives the novice ML programmer the impression that the solution either cannot or should not be updated to the model solution:
fun map f [] = []
| map f (x::xs) = f x :: map f xs
It seems then that the type signatures, which are supposed to aid the student, prevents them from pattern matching. I cannot say if this is because they think that the type signatures cannot be removed or if they should not be removed. It is, of course, a matter of style whether they should (and where), but the student should be enabled to explore a style of type inference.
By using a let or local bound function, and shadowing
you can declare the function, and then assign it to a value.
using local for this is more convenient, since it has the form:
local decl in decl end, rather than let decl in expr end,
meaning let's expr, wants a top-level argument f
val map = fn f => let fun map = ... in map end
I don't believe people generally use local, anymore primarily because modules can do anything that local can, and more, but perhaps it is worth considering it as an anonymous module, when you do not want to explain modules yet.
local
fun map (f : 'a -> 'b) (x::rest : 'a list) : 'b list
= f x :: map f rest
| map _ ([]) = []
in
val (map : ('a -> 'b) -> 'a list -> 'b list) = map;
end
Then when it comes time to explain modules, you can declare the structure inside the local, around all of the declarations,
and then remove the local, and try to come up with a situation, where they have coded 2 functions, and it's more appropriate to replace 2 locals, with 1 structure.
local
structure X = struct
fun id x = x
end
in val id = X.id
end
perhaps starting them off with something like the following:
exception ReplaceSorryWithYourAnswer
fun sorry () = raise ReplaceSorryWithYourAnswer
local
(* Please fill in the _'s with the arguments
and the call to sorry() with your answer *)
fun map _ _ = sorry ()
in
val map : ('a -> 'b) -> ('a list) -> ('b list) = map
end

How to merge set of finite maps?

I can merge two finite maps as follows:
value "fmadd
(fmap_of_list [(1::nat,2::nat)])
(fmap_of_list [(2::nat,3::nat)])"
But when I try to merge a set of maps:
value "ffold fmadd fmempty {|
fmap_of_list [(1::nat,2::nat)],
fmap_of_list [(2::nat,3::nat)]|}"
I get the following error:
Wellsortedness error:
Type nat ⇀⇩f nat not of sort finite
No type arity fmap :: finite
According to definition of fmap, it's domain is finite:
typedef ('a, 'b) fmap = "{m. finite (dom m)} :: ('a ⇀ 'b) set"
morphisms fmlookup Abs_fmap
proof
show "Map.empty ∈ {m. finite (dom m)}"
by auto
qed
But why fmap is not finite?
To answer your immediate question:
But why fmap is not finite?
Every fmap has a finite domain, but it is not necessarily the case that there are only finitely many values of type ('a, 'b) fmap. For example, there are infinitely many finitely-sized mappings from nat to nat.
The problem you're observing is deeper than that: I believe there is no proper code setup for ffold. If I try to compute
ffold funion fempty {|
fset_of_list [(1::nat,2::nat)],
fset_of_list [(2::nat,3::nat)]|}
... the error message is similar. For now, I would recommend rewriting it as fold on lists:
fold fmadd [
fmap_of_list [(1::nat,2::nat)],
fmap_of_list [(2::nat,3::nat)]] fmempty
It's not the same but it might be useful for your application.

SML: If -> is right associative

Ullman's book, Elements of ML Programming, introduces a simple version of the map function defined as follows:
fun simpleMap(F, nil) = nil
| simpleMap(F, x::xs) = F(x)::simpleMap(F, xs);
val map = fn : ('a -> 'b) * 'a list -> 'b list
Given that -> is right associative, wouldn't you parenthesize like this:
('a -> 'b) * ('a list -> 'b list) ?
But this is incorrect since the domain type is a tuple consisting of the function and a list and the range type is just a list.
Where am I going wrong?
Thanks!
In SML, the type operator * binds more tightly than ->: it has a higher precedence just like * has a higher precedence than + in arithmetic.
This is why string * string -> string is the same as (string * string) -> string and not string * (string -> string). To read your example, we'd need to put parentheses around the * before worrying about how -> associates:
(('a -> 'b) * 'a list) -> 'b list

Resources