I am trying to implement a node delete function for a Binary Search Tree in SML/nj.
However I am getting a constraint error, that I don't understand why...
datatype 'a tree = Empty | Node of 'a * 'a tree * 'a tree;
datatype 'a stree = STree of ('a * 'a -> bool) * ('a * 'a -> bool) * 'a tree;
fun removeMin Empty = Empty
| removeMin (Node(_,Empty,r)) = r
| removeMin (Node(k,l,r)) = Node(k, removeMin l, r);
removeMin: 'a tree -> 'a tree;
fun get_left_most Empty = Empty
| get_left_most (Node(k,Empty,r)) = Node(k,Empty,r)
| get_left_most (Node(_,l,_)) = get_left_most l;
get_left_most: 'a tree -> 'a tree;
fun get_key (Node(k, l, r)) = k;
get_key: 'a tree -> 'a;
fun tree_empty Empty = true
| tree_empty (Node(_,_,_)) = false;
tree_empty: 'a tree -> bool;
fun remove v (STree(f, g, stree2)) =
let
fun remove2 v Empty = Empty
| remove2 v (Node(k,l,r)) =
if f(v, k) then
if (tree_empty l) then r
else if (tree_empty r) then l
else Node(get_key (get_left_most r), l, removeMin r)
else if g(v, k) then Node(k, (remove2 v l), r)
else Node(k, l, remove2 v r);
in
STree(f, g, (remove2 v stree2))
end;
remove: 'a -> 'a stree -> 'a stree;
This is the error that I am getting: (for get_key)
Warning: match nonexhaustive
Node (k,l,r) => ...
Does anyone know why this is happening?
Your comparison using = in remove means that the tree must contain equality types (hence the two ' characters in the ''Z type variable that SML inferred) but you have claimed that it's more general: remove: 'a -> 'a stree -> 'a stree;.
You need to either only use equality types (i.e. declare remove: ''a -> ''a stree -> ''a stree;)
or redefine remove2 to use case analysis instead of comparison.
For instance,
| remove2 v (node as Node(k, Empty, Empty)) = if f(v, k) then Empty else node
Related
I am writing loop by recursion and I have problem:
let isRectangleIn a b c d =
if (a > c && b > d) || (a>d && b>c)
then
"TAK"
else
"NIE";;
let rec loop k =
if k = 0 then 0 else
let a = read_int () in
let b = read_int () in
let c = read_int () in
let d = read_int () in
Printf.printf "%s \n" (isRectangleIn a b c d)
loop (k-1);;
let i = read_int ();;
let result = loop i;;
Compiler says that
This expression has type
('a -> 'b -> 'c, out_channel, unit, unit, unit, 'a -> 'b -> 'c)
CamlinternalFormatBasics.fmt
but an expression was expected of type
('a -> 'b -> 'c, out_channel, unit, unit, unit, unit)
CamlinternalFormatBasics.fmt
Type 'a -> 'b -> 'c is not compatible with type unit
but I dont understand what i am doing wrong. Can somebody help me?
Whenever you see an error displaying CamlinternalFormatBasics.fmt, it means that a printf function is involved. Moreover, if there is a function type (here 'a -> 'b -> 'c) in the first parameter of the format, the error is that printf have too many argument compared to the format string.
In your case, the format string is "%s \n", which requires one argument, however you are using it with 3 arguments:
Printf.printf "%s \n" (isRectangleIn a b c d) loop (k-1)
(One can notice that there is as many supernumerary arguments in this function application and in the function type in the type error message.)
The root issue here is a missing ; between the printf expression and loop (k-1):
Printf.printf "%s \n" (isRectangleIn a b c d);
loop (k-1)
To avoid this kind of issue, it is generally advised to use ocp-indent (or ocamlformat) to indent code automatically and avoid deceitful indentation. For instance, ocp-indent would have indented your code as
Printf.printf "%s \n" (isRectangleIn a b c d)
loop (k-1);;
manisfesting the fact that printf and loop are not as the same level.
I am creating monads in OCaml and need to compose them, so I created transformers. I implemented the regular monad in terms of the transformer with the Identity monad:
module type MONAD = sig
type 'a m
val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
val return : 'a -> 'a m
end
module Identity : MONAD = struct
type 'a m = 'a
let (>>=) m f = f m
let return x = x
end
module OptionT (M : MONAD) : MONAD with type 'a m := ('a option) M.m = struct
type 'a m = ('a option) M.m
let (>>=) m f = M.(>>=) m (fun option ->
match option with
| Some x -> f x
| None -> M.return None)
let return x = M.return ## Some x
end
module Option = OptionT(Identity)
However, I can't do this:
open Option
let _ = (Some 1) >>= (fun x -> Some (x + 1))
The errors are:
(Some 1)
This expression has type 'a option
but an expression was expected of type 'b option Identity.m
Some (x + 1)
This expression has type 'a option
but an expression was expected of type 'b option Identity.m
If I try to fix the error with module Identity : MONAD with type 'a m = 'a I get an error at module Option = OptionT(Identity) that states that
The type `m' is required but not provided
It seems that now, 'a has replaced 'a m in the signature.
Doing
module Option : MONAD with type 'a m := 'a option = struct
type 'a m = 'a option
let (>>=) m f =
match m with
| Some x -> f x
| None -> None
let return x = Some x
end
works just fine.
How do I tell the compiler that a module implements a signature so that a type declared in the signature is the same as another type, while still keeping the signature's original type declaration?
It seems that now, 'a has replaced 'a m in the signature.
This the effect of destructive substitution, when you write
module Identity : MONAD with type 'a m := 'a
you are asking the compiler to substitute all instance of 'a m by 'a.
Contrarily, standard with constraint adds a type equality to the module type
module Identity : MONAD with type 'a m = 'a
Looking at your various examples, it seems that you have confused the two, and are using destructive substitution when you meant to add a type constraint:
module OptionT(X:Monad) : MONAD with type 'a m = 'a = …
(* or *) module Option : MONAD with type 'a m = 'a option = …
and not
module OptionT(X:Monad) : MONAD with type 'a m := 'a = …
(* nor *) module Option : MONAD with type 'a m := 'a option = …
This expression has type 'a option but an expression was expected of type 'b option Identity.m
And indeed, the compiler does not know anything about Identity except that its signature is MONAD. (: MONAD) is not something that merely helps the compiler, it hides all information about Identity except that its signature is MONAD.
So, you can add a type equality for that
module Identity : MONAD with type 'a m = 'a = ...
and it works.
I want to implement Option Monad in SML, so I can use them the same way they can be used in haskell. What I did, does not work.
infix 1 >>=
signature MONAD =
sig
type 'a m
val return : 'a -> 'a m
val >>= : 'a m * ('a -> 'b m) -> 'b m
end;
structure OptionM : MONAD =
struct
type 'a m = 'a option
val return = SOME
fun x >>= k = Option.mapPartial k x
end;
val x = OptionM.return 3;
x (OptionM.>>=) (fn y => NONE);
Result:
stdIn:141.1-141.31 Error: operator is not a function [tycon mismatch]
operator: int OptionM.m
in expression:
x OptionM.>>=
What can I do to make the last line work?
Unlike in Haskell, qualified infix operators (such as A.+ or Option.>>=) are not infix in SML. You need to use them unqualified, e.g. by either opening the module or by rebinding it locally.
Btw, you probably want to define >>= as right-associative, i.e., use infixr.
Also, SML has stricter precedence rules than Haskell. That will make it somewhat more tedious to chain several uses of >>= with lambdas, because you have to parenthesise each fn on the right:
foo >>= (fn x => bar >>= (fn y => baz >>= (fn z => boo)))
I had previously posted problems like the following, but have not yet found a solution. I am having a store (mapping) from a record type (with five members) to a string value. A fold with a function guarding on the three elements of the record and returns a mapping (string to string). I need to solve some lemmas like gsc_MapsTo_iff_right below.
The code may contain some awkward syntax (for example fold) as I am not expert of Coq. Sorry for that.
Thank you for your help.
Wilayat
Require String.
Record c_id : Type := build_c_id {
c_id_d : String.string;
c_id_p : String.string;
c_id_s : bool;
c_id_h : bool;
c_id_k : String.string
}.
Definition skey := String.string.
Definition st (elt:Type) := list (String.string * elt).
Variable elt : Type.
Parameter Sadd : skey -> String.string -> st String.string -> st String.string.
Parameter SMapsTo : skey -> String.string -> st String.string -> Prop.
Definition ckey := c_id.
Definition ct (e:Type) := list (ckey * elt).
Implicit Type cm: ct elt.
Parameter Cadd : ckey -> String.string -> ct String.string -> st String.string.
Parameter CMapsTo : ckey -> String.string -> ct String.string -> Prop.
Parameter elements : ct String.string -> list (ckey*String.string).
Fixpoint rec_fold {A : Type} (f: ckey -> String.string -> A -> A) (l : list (ckey * String.string)) (b: A) : A :=
match l with
| nil => b
| cons (k, v) t => f k v (rec_fold f t b)
end.
Fixpoint fold {A: Type} (f: ckey -> String.string -> A -> A)
(cm: ct String.string) (b:A) : A :=
rec_fold f (elements cm) b.
Parameter empty : st String.string.
Axiom str_dec : forall a b : String.string, {a = b} + {a <> b}.
Definition str_eqdec (a b: String.string):bool :=
if str_dec a b then true else false.
Notation "x =?= y" := (str_eqdec x y) (at level 30).
Definition andb (b1 b2:bool) : bool := if b1 then b2 else false.
Notation "x & y" := (andb x y) (at level 40).
Definition get_sc (d p: String.string) (ckm: ct String.string)
: st String.string :=
fold
(fun cki v zm => if d =?= cki.(c_id_d) &
p =?= cki.(c_id_p) &
(negb (cki.(c_id_s)))
then Sadd cki.(c_id_k) v zm
else zm )
ckm
empty.
Lemma gsc_MapsTo_iff_right:
forall p d zk zv zh cm,
CMapsTo (build_c_id d p false zh zk) zv cm ->
SMapsTo zk zv (get_sc d p cm).
Proof.
Admitted.
I have made a class method, and I'd like to have this type :
unit -> (dir -> 'b)
But my actual method:
method iter () = fun x -> match x with
| Up -> if (Stack.is_empty pz) then raise Stack.Empty else if (Stack.length pz = 1) then failwith "Cannot go up" else (ignore (Stack.pop pz) ; {< a = (Stack.top pz) >})
| Down(v) -> match (Stack.top pz) with
| Noeud(o, {contents = []}) -> raise Not_found
| Noeud(o, {contents = l}) -> if mem_assoc v l then ((Stack.push (assoc v l) pz) ; {< a = (Stack.top pz) >} ) else raise Not_found
has the type unit -> dir -> 'b
How can I make it so it becomes the first type?
Here are the custom types :
type 'a arbre = Noeud of 'a option ref * (char * 'a arbre) list ref
type dir = Up | Down of char
Edit: I need this so it can comply to a certain interface, and because of the type mismatch, it won't compile.
Thanks!
This is not the problem. unit -> (dir -> 'b) and unit -> dir -> 'b are the same type in OCaml! (the type arrow is right-associative)
Could you show us the actual error message so we can know where the problem lies?
Addendum: have you actually tried this? If there is no other issue, then you'll find it'll just work.