Why does this compile?
fun foo (h::t) =
h = hd(t);
But this does not
fun foo (h::t) =
PolyML.print (h::t);
print "\n";
h = hd(t);
?
Value or constructor (h) has not been declared Found near =( h, hd(t))
Value or constructor (t) has not been declared Found near =( h, hd(t))
Exception- Fail "Static errors (pass2)" raised
I think your frustration with the language prevents you from solving your problem(s) more than the limitations of the language. As I said in a previous answer, semicolons cannot be used like you used them. You need to wrap those statements inside parentheses:
fun foo (h::t) =
(
PolyML.print (h::t);
print "\n";
h = hd(t)
)
Furthermore, you first snippet doesn't need a semicolon:
fun foo (h::t) =
h = hd(t)
Here's the thing, in SML semicolons are not used to terminate statements, they're used to separate expressions. Think of ; as a binary operator, just like + or -. With the added constraint that you need parentheses around.
Also, you're probably using the = operator in the wrong way inside h = hd(t). It's not assignment, it's an equality check, just like == in other languages. If you want assignment, you need a ref type.
It's probably better to ask what exactly you're trying to solve, because at this point you're totally misunderstanding the syntax and semantics of SML and we can't really write a tutorial on in here.
Related
Trying to cobble together a lambda calculus interpreter as a noob project and I have come upon a syntax problem I cannot quite figure out.
Problem being that two constructors of a type behaves the same in some respects and I would like to avoid code duplication. See code below.
type term =
| Lam of string * term * term
| Pi of string * term * term
let rec subst x t s = match s with
| Lam (y,r,q) | Pi (y,r,q) ->
if x = y then LAMORPI (y, subst x t r, q)
else [...]
What I think are called or-patterns seemed like a good fit but I cannot get it to work. Figured perhaps that is what as is for, but I cannot seem to partially as something, which is what I had in mind for LAMORPI to be doing. This case seems like it would have a neat or commonly used idiomatic solution but my google-fu is not strong enough.
What is a usual or otherwise possible solution for this?
It is not possible to use or-pattern in expressions. (And this potential feature raises some issues: see http://gallium.inria.fr/blog/pattern-synonyms-as-expressions for a discussion)
One possibility is to refactor your type to expose the fact that the two constructors only differ by a tag:
type kind = Lam | Pi
type term =
| LamPi of tag * string * term * term
| ...
let rec subst x t s = match s with
| LamPi (tag,y,r,q) ->
if x = y then LamPi (tag, y, subst x t r, q)
else ...
I have the following function :
let extract n l =
let rec aux acc pro = function
|[] -> acc
|a::b -> if (List.length pro) = n then aux (pro::acc) [] (a::b) else aux acc (a::pro) b; aux acc (pro) b
in aux [] [] l
As you can see in my pattern matching at the second test's case I am calling two times the function. Is it possible ?
So it is possible to have this kind of function :
let rec some_function = function
| [] ->[]
| a::b -> some_function b; some_function b (*so I am calling two times the function in a single test*)
I am asking this question because here I have the following warning :
File "main.ml", line 4, characters 48-72:
Warning 10: this expression should have type unit.
So there is a problem at the exact place I called two times my recursive function.
It might be because I am using ; but in this case how could I seperate these two calls ?
Thank you !
To add onto FlorianWeimer's answer, some information about your error message.
Warning 10: this expression should have type unit.
OCaml is strongly typed. Therefore, if a function returns, say, an integer or a list, and you don't do anything with it, it'll wonder what's going on and warn you.
A function call like print_int 5; returns (), which is of type unit. That basically means that it returns nothing because you're not calling it to compute something, but to do something. It has done that thing and now it returns and you move on.
But a function call like float_of_int 5;, that returns a value (the float 5.0). You (probably) didn't call it to do something, but to compute something, and what it returns is what interests you. Same goes for arithmetic expressions like 3+6; or for straight up values like 10; or "abc"; or [];.
That's why, if you write one of these things that have a value and you don't use that value (in an assignment, or as a parameter of another function), OCaml warns you. It tells you "I computed something that I didn't assign, didn't return, and didn't use as the argument of something else. Usually, things of type unit are the only things like that. Are you sure you don't have a bug in your code?"
Sometimes you know what you're doing and you don't want that warning. In that case, you can call the ignore function. ignore will take anything and ignore it, returning (). For instance, ignore 5; or ignore (float_of_int 10); won't throw the "this expression should have type unit" warnings that you'd get with 5; or float_of_int 10;.
It is possible in the sense that the compiler accepts it, but it only makes sense if you do something with the result (or the function has a side effect). The classic example for two function calls is the recursive computation of the Fibonacci sequence:
let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)
I am new to SML and I have written a program that takes 3 integer numbers (n,z,k) and wants to compare them with a value given in the program, if the statement is correct it will return true, else false. conditions and values should be equal simultaneously, I mean program will return true if all these numbers are equal to the value given in the program, so my if statement should check 3conditions at the same time.
my problem is that I don't know how I can write all these 3conditions in one if clause, because SML don't recognize for example & or ^ as and!
for example i want to check whether if(n==8 && k==5 && z==9). what should I use instead of &
here is the code:
fun EvalR (n: int , k: int , z:int) =
if (n=8 ???) then true
else false;
Since Ashkan Parsa referred to the CS317 SML Style Guide, I thought I would point out what you might derive from it.
Let function names start with a lower case, e.g. evalR.
Don't write if ... then true else false; simply write ....
Some disagree; type annotations certainly are helpful, but so is type inference.
As nazila says, the and operator in Standard ML is called andalso.
So,
fun evalR (n, k, z) =
n = 42 andalso k = 43 andalso z = 0
It might seem comfusing that the function body contains =s at the same time as the function being defined with a = to separate the function arguments from the function body. Just think of the latter =s as value operators and the first = as a part of declaring things (like types, values, functions, etc.)
I found it. we can use andalso in SML.
here is a code snippet I wrote.
let trans_binop _ =
let l = trans_exp lexp in
B.binop_build op l r
let trans_exp exp =
match exp with
| _->
trans_binop binop
The above code is simplified. And these two functions are defined inside one Module. The problem is that: the first function needs to refer to the second one, while the second one needs to refer to the first.. Then it just cannot compile.
I basically don't want to put one let expression into another one, because I think it is not decent logically..
Could any one give me some help on this question? Thanks
Use and to declare mutually recursive functions
let rec trans_binop _ =
let l = trans_exp lexp in
B.binop_build op l r
and trans_exp exp =
match exp with
| _->
trans_binop binop
You have to define your functions as mutually recursive. That means you have to use the keyword and in the place of the second let. See also https://ocaml.org/learn/tutorials/labels.html
I have an ocaml type :
type t = A | B | ...
and a function to print things about that type :
let pp_t fmt x = match x with
| A -> Format.fprintf fmt "some nice explanations about A"
| B -> Format.fprintf fmt "some nice explanations about B"
| ...
How could I write a function to print all the explanations ? Something equivalent to :
let pp_all_t fmt =
Format.fprintf fmt A;
Format.fprintf fmt B;
...
but that would warn me if I forget to add a new constructor.
It would be even better to have something that automatically build that function,
because my problem is that t is quiet big and changes a lot.
I can't imagine how I can "iterate" on the type constructors, but maybe there is a trick...
EDIT: What I finally did is :
type t = A | B | ... | Z
let first_t = A
let next_t = function A -> B | B -> C | ... | Z -> raise Not_found
let pp_all_t fmt =
let rec pp x = pp_t fmt x ; try let x = next_t x in pp x with Not_found -> ()
in pp first_t
so when I update t, the compiler warns me that I have to update pp_t and next_t, and pp_all_t doesn't have to change.
Thanks to you all for the advices.
To solve your problem for a complicated and evolving type, in practice I would probably write an OCaml program that generates the code from a file containing a list of the values and the associated information.
However, if you had a function incr_t : t -> t that incremented a value of type t, and if you let the first and last values of t stay fixed, you could write the following:
let pp_all_t fmt =
let rec loop v =
pp_t fmt v;
if v < Last_t then loop (incr_t v)
in
loop First_t
You can't have a general polymorphic incr_t in OCaml, because it only makes sense for types whose constructors are nullary (take no values). But you can write your own incr_t for any given type.
This kind of thing is handled quite nicely in Haskell. Basically, the compiler will write some number of functions for you when the definitions are pretty obvious. There is a similar project for OCaml called deriving. I've never used it, but it does seem to handle the problem of enumerating values.
Since you say you want a "trick", if you don't mind using the unsafe part of OCaml (which I personally do mind), you can write incr_t as follows:
let incr_t (v: t) : t =
(* Please don't use this trick in real code :-) ! See discussion below.
*)
if t < Last_t then
Obj.magic (Obj.magic v + 1)
else
failwith "incr_t: argument out of range"
I try to avoid this kind of code if at all possible, it's too dangerous. For example, it will produce nonsense values if the type t gets constructors that take values. Really it's "an accident waiting to happen".
One needs some form of metaprogramming for such tasks. E.g. you could explore deriving to generate incr_t from the Jeffrey's answer.
Here is a sample code for the similar task : https://stackoverflow.com/a/1781918/118799
The simplest thing you can do is to define a list of all the constructors:
let constructors_t = [A; B; ...]
let pp_all_t = List.iter pp_t constructors_t
This is a one-liner, simple to do. Granted, it's slightly redundant (which gray or dark magic would avoid), but it's still probably the best way to go in term of "does what I want" / "has painful side effects" ratio.