Consider the following example of a list in SML: [[("foo",~10.0)],[("goo",~8.0)]].
I would link to write a function which will delete the main brackets meaning the output will be:
[("foo", ~10.0), ("goo, ~8.0)]
The function I wrote:
fun inner_list [[]] = [] | inner_list [] = []
| inner_list ((((x:(string*real))::xt)::xs)) = x :: inner_list xs;
It works for most cases but I know that I didn't check one of the cases. I think this case is:
[[],("foo", ~10.0)]
I know that I didn't handle one of the cases because the compiler alerts:
stdIn:1.6-2.68 Warning: match nonexhaustive
nil :: nil => ...
nil => ...
(x :: xt) :: xs => ...
I read other articles related with the Warning: match nonexhaustive warning, but I didn't understand how to solve it with my program.
How to handle the other case?
EDIT I know that my list contains only one list. this is why I don't use xt
How about the built-in List.concat?
List.concat [[("foo",~10.0)], [("goo",~8.0)]] =
[("foo",~10.0), ("goo",~8.0)]
Related
What does this function do in OCaml?
let rec pack xs =
match xs with
| [] -> []
| [x] -> [[x]]
| first :: second :: rest ->
if first = second then
let (firstC :: restC) = pack rest in
(first :: firstC) :: restC
else
[first] :: pack rest
I especially am confused with the line:
let (firstC :: restC) = pack rest in
(first :: firstC) :: restC
The let expression in OCaml looks like this:
let <pattern> = <expr1> in <expr2>
In the expression you're asking about, the pattern is firstC :: restC. This is a pattern that matches any non-empty list. The first element of the list is bound to firstC and the rest of the list is bound to restC.
The pattern is matched against expr1, which in your case is pack rest. If pack rest returns a non-empty list, this gives values to firstC and restC.
These bindings are then used in the expr2 of your example, which is:
(first :: firstC) :: restC
This is a list made by adding first to the beginning of the list firstC and then adding this list to the beginning of the list of lists restC.
If pack rest returns an empty list the result will instead be an exception.
Since pack rest can indeed return an empty list, this code looks fairly suspect to me. Here's an example where it fails in this way:
# pack [3; 3];;
Exception: Match_failure ("//toplevel//", 5, 54).
Note that compiler warns you that the pattern firstC :: restC doesn't cover every case. Hence it might produce an exception (which it does).
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
I hope this is helpful.
I'm writing a recursive function that builds a list, but has some conditions where, if met, the function should ignore the list that's been built so far and simply return an empty list on its own.
A simple example:
func (x:xs)
| x < 10 = [x] ++ func xs
| otherwise = ("return an empty list without the already built up list")
So if xs was a list [1 .. 12] then once it's built a list that's [1..9] then when it reaches 10, it'll disregard the list it's built and just return an empty array [], and not return an empty array that's passed back to the already built up list.
Is there a way to do this in Haskell? I've tried doing return [] but it gave me the error:
Couldn't match expected type βIntβ with actual type β[t0]β
return is not a statement in Haskell, but even if it was it would not work anyway. Since due to recursion, you then return that list at that specific level.
It looks however that you simply want to know if all elements are smaller than 10. If that is the case, you return the entire list, otherwise you return an empty list.
You can do that with:
func :: (Num a, Ord a) => [a] -> [a]
func xs | all (< 10) xs = xs
| otherwise = []
or we can use recursion, and make use of Maybe:
func :: (Num a, Ord a) => [a] -> Maybe [a]
func [] = Just []
func (x:xs) | x < 10 = fmap (x:) (func xs)
| otherwise = Nothing
We can then later convert the Nothing value with fromMaybe :: a -> Maybe a -> a to an empty list, although a Maybe might be better idea here, that allows us to differentatie between func [] and func [14] for example.
I'am writing this function for a MOOC. It's job is to remove a string from the list and return that list without the string as a SOME or return NONE is the string is not there.
I wrote the code below but whenever I try to run it I get the following error: Error: non-constructor applied to argument in pattern: -.
exception NotFound
fun all_except_option (str : string, strs : string list) =
let
fun remove_str (strs : string list) =
case strs of
[] => raise NotFound
| str'::strs' => if same_string(str, str') then strs' else str'::remove_str strs'
in
SOME (remove_str strs) handle NotFound => NONE
end
And where's one test to run it:
val test01-01 = all_except_option ("string", ["string"]) = SOME []
edit
forgot to include the same_string function that was provided to us to simplify types
fun same_string(s1 : string, s2 : string) =
s1 = s2
Figured out the problem. Seems like SML doesn't like hyphens, like the one I had in the test:
val test01-01 = all_except_option ("string", ["string"]) = SOME []
I changed to underscore instead and now it works.
val test01_01 = all_except_option ("string", ["string"]) = SOME []
Since you've already solved this task, here's a way to write it without using exceptions:
fun all_except_option (_, []) = NONE
| all_except_option (t, s :: ss) =
if s = t
then SOME ss (* don't include s in result, and don't recurse further *)
else case all_except_option (t, ss) of
SOME ss' => SOME (s :: ss')
| NONE => NONE
Having a recursive function return t option rather than t makes it more difficult to deal with, since upon every recursive call, you must inspect if it returned SOME ... or NONE. This can mean a lot of case ... of ... s!
They can be abstracted away using the library function Option.map. The definition is found in the standard library and translates into:
fun (*Option.*)map f opt =
case opt of
SOME v => SOME (f v)
| NONE => NONE
This bit resembles the case ... of ... in all_except_option; rewriting it would look like:
fun all_except_option (_, []) = NONE
| all_except_option (t, s :: ss) =
if s = t
then SOME ss (* don't include s in result, and don't recurse further *)
else Option.map (fn ss' => s :: ss') (all_except_option (t, ss))
Well this Parse error: "in" expected after [binding] (in [expr])
is a common error as far I have searched in Ocaml users, but in the examples I saw I didnt found the answer for my error, then I will explain my problem:
I declared this function:
let rec unit_propag xs =
let cuAux = teste xs
let updatelist = funfilter (List.hd(List.hd cuAux)) (xs)
let updatelist2 = filtraelem (negar(List.hd(List.hd cuAux))) (updatelist)
if(not(List.mem [] xs) && (teste xs <> []))
then
unit_propag updatelist2
;;
The functions I am using inside this code were declared before like this:
let funfilter elem xs = List.filter (fun inner -> not (List.mem elem inner)) xs;;
let filtraele elem l = List.map( fun y -> List.filter (fun x -> x <> elem) y)l;;
let teste xs = List.filter(fun inner ->(is_single inner)inner)xs;;
let is_single xs = function
|[_] -> true
|_ -> false
;;
let negar l =
match l with
V x -> N x
|N x -> V x
|B -> T
|T -> B
;;
But not by this order.
Well they were all doing what I wanted to do, but now when I declared unit_propag and tried to compile, I had an error in line of
let cuAux = teste xs
It said:
File "exc.ml", line 251, characters 20-22:
Parse error: "in" expected after [binding] (in [expr])
Error while running external preprocessor
Command line: camlp4o 'exc.ml' > /tmp/ocamlpp5a7c3d
Then I tried to add a ; on the end of each function, and then my "in" error appeared on the line of the last function, is this case unit_propag updatelist2
What I am doing wrong? people usually say that this kind of errors occurs before that code, but when i comment this function the program compiles perfectly.
I need to post more of my code? Or i need to be more clear in my question?
Is that possible to do in Ocaml or I am doing something that I cant?
Thanks
The error message says you're missing in, so it seems strange to solve it by adding ; :-)
Anyway, you're missing the keyword in after all the let keywords in your function unit_propag.
You should write it like this:
let rec unit_propag xs =
let cuAux = teste xs in
let updatelist = funfilter (List.hd(List.hd cuAux)) (xs) in
let updatelist2 =
filtraelem (negar(List.hd(List.hd cuAux))) (updatelist)
in
if (not (List.mem [] xs) && (teste xs <> [])) then
unit_propag updatelist2
The basic issue has been explained many times here (as you note). Basically there are two uses of the keyword let. At the outer level it defines the values in a module. Inside another definition it defines a local variable and must be followed by in. These three lets are inside the definition of unit_propag.
Another attempt to explain the use of let is here: OCaml: Call function within another function.
I want the last value in list of SML.
for example, 1::2::3 => 3
I tried use "last", but it didn't work.
I tried to implement it, like this:
val rec last =
fn (h::list) => last (list)
| (h::nil) => h
| (nil) => nil;
But it gives me problem: match redundant.
Thank you for your help.
I doubt that the case of (h::nil) is redundant because it is a special case of (h::list). I think you should reorder your match cases:
exception Empty
val rec last =
fn (h::nil) => h
|(h::list) => last (list)
| (nil) => raise Empty;
By the way, List.last should work because it's a part of SML Basis Library.
Could also be done as easy as that:
exception Empty
fun lastinList [] = raise Empty
| lastinList l = hd(rev(l));