I have declared a list l=[];; and now trying to append tuples into this list using '#'. But I am not able to do so. Can anyone please help me sorting this out.
let l = []
for x = 1 to 10 do
l <- l#[(x,x+10)]
done;;
And want final answer as: l=[(1,10),(2,20),(3,30).....]
Your definition of l means that l is immutable. You define its value as [], and this can never be changed.
If you want to be able to change l, you need to define it as a mutable value. One simple way to do this is to make it a "ref":
# let l = ref [];;
val l : '_a list ref = {contents = []}
After this you can get the value of l with the ! operator and change the value using the := operator:
# !l;;
- : '_a list = []
# l := !l # [3];;
- : unit = ()
# !l;;
- : int list = [3]
However, this code is not idiomatic OCaml. If you're studying OCaml academically, it might be better to learn to work with immutable values.
Update
Here are some hints on writing recursive functions. I don't want to spoil the exercise by writing the code for you.
The way to solve a problem recursively is to answer questions like this:
What general problem am I trying to solve? In your case, you're trying to create a list of pairs of some length with some arithmetic properties.
What is the most trivial case of this problem? In your case, the most trivial case is when the desired length is 0 (in which case the list is empty).
If I have a non-trival case of the problem, how can I break it into easily calculated answers and smaller cases of the same problem? You want to assemble these into the full answer. In your case, the smaller pieces would be the first element of the result (easily calculated), and a list that's one shorter (smaller case of the same problem).
Then your code looks like this for the garden variety recursive function with some number of parameters (say a, b, c, d):
let rec f a b c d =
if <<this is the trivial case>> then
<<the answer is obvious>>
else
let tp = <<answer to tiny piece of the problem>> in
let (a', b', c', d') = <<rest of the problem (smaller)>> in
let smres = f a' b' c' d' in
<<combine tp and smres>>
Related
I am a beginner with OCaml. I would like to skip the first element of my list.
Here is my list:
let l = [1;2;3;4;5;6;7;2;1];;
I want to use this in my FOR:
let l = List.tl l;
here is my full code:
let l = [1;2;3;4;5;6;7;2;1];;
let n = 1;;
let counter = ref 0;;
for i = 0 to (List.length l) do
if List.hd l = n then counter := !counter + 1;
print_int(!counter);
print_string("\n");
let l = List.tl l
done;;
But I have errors in the DONE and it says syntax error.
Can anyone help me please?
Your problem is that let always requires a matching in. The full expression looks like this:
let var = expr1 in expr2
Since you're missing the in part, you get a syntax error.
However, the deeper problem is that you're trying to modify the value of l. The way you have defined l, it's immutable. You can't change its value. If you want to be able to change its value you can define it as a reference, as you have done for counter.
(There is another form of let used at the top level of a module. This form doesn't have a matching in. But your code isn't defining a top-level name, so this is not relevant.)
F# makes it easy to unpack tuples. Unpacking lists is also feasible, but the compiler issues a warning:
let m = [1; 2; 3]
let [a; b; c] = m
// Incomplete pattern matches on this expression. For example, the value '[_;_;_;_]' may indicate a case not covered by the pattern(s)
Is there a way to avoid this warning?
You can disable warnings per file by using the #nowarn directive (in your case #nowarn "25") or you can disable warnings on the command line with --nowarn.
Check out the F# Compiler Directives for details.
There is currently no way to re-enable warnings again, when first disabled.
Your match may (unexpectedly) result in a runtime error if the number of elements cannot be unpacked to [a;b;c], so instead you can use a complete match that is explicit about the risc:
let m = [1;2;3]
let (a,b,c) =
match m with
| [a;b;c] -> (a,b,c)
| _ -> failwith "Expected exactly three items in m"
What would happen if your list m has 2 or 4 elements?
There is obviously a way, plain old pattern matching:
let a, b, c =
match m with
| [a;b;c] -> a,b,c
| _ -> ... // handle the length!=3 case
F# allows you to deconstruct the right-hand side objects that way when there's clear that you only have a single case you need to cover. This is the case with tuples, since there's only one tuple type that would match both the left and the right hand side. Something like this obviously would not compile, because the types won't match:
let m = 1, 2
let a, b, c = m
Yet in your case there's no guarantee that you're not in fact in this scenario:
let m = [ 1; 2 ]
let [1;2;3] = m
You're in fact asking the compiler to allow non-exhaustive pattern matching. You can disable the warning as noted in the other answer, but you're inviting runtime errors that way.
One obvious, but hardly elegant, way is:
let m = [1; 2; 3]
let a = List.item 0 m
let b = List.item 1 m
let c = List.item 2 m
You can write a helper function to make it neater:
let unpack3 x = (List.item 0 x, List.item 1 x, List.item 2 x)
let (a, b, c) = unpack3 m
Basically a list is not a great fit if you know you are always going to have a fixed number of items.
Ok so have been faced with a problem where basically I have a been told to make a multiset, or a list of tuples. (Char,Int) and then I have to write a function that takes a item and inserts it into this list, but if there is already a matching tuple in the list it increases the Int.
i.e. i had a list [(p,2),(w,3)] and i get another w it should give [(p,2),(w,4)]
How would you go about it, i've tried
listAdd :: Char->Int->ListOfT -> ListOfT
listAdd c i l
|length l == 0 =(c,i):l
|fst l == c = (c,i+1):l
but this gives loads of errors, i need to remove the list element at that point and replace it with with (c,i+1), so how do i remove from the list and how to i get i+1? also how do you make a loop which will go through all the elements in a list?
And i can't use any of the import Data stuff
I know this is asking a ton but any help would be great thanks.
Neo
Okay can this code be fiddled with so it can be used tto make tuples of any items not just chars. so i could load it up and make a list of tuples with stirngs instead, close it then load it up again and make a list of tuples of ints?
ok I think your idea is not bad you just have to get the details straight.
The loop you asked about is usually either done with recursion (as a list is a recursive structure that's a great idea) or with some higher order functions like map, filter, foldr, ... that will hide the recursion from you (you could say they abstract away the repeating stuff) - anway in this case I think the easiest way is just to go with what you started and use the direct recursion.
Here is a simple version (you maybe want to extent) that does the basic stuff:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c ((c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = (c',i) : listAdd c xs
as you can see the first case is very similar to what you had: if the dictionary (the second argument) is the empty list than you just add a new tuple with the char to insert and the number 1
if not then you check if the first element in the dictionary has the same character (c' here), if yes then you increase the count and if not you let this element stand as it is and recursively search through the rest of the dictionary.
Also note that you can use pattern matching here to not only deconstruct the dictionary into head::tail form but also deconstruct the head into (..,..) tuple parts as well.
If you want you can use a # in there to and get the second case a bit more concise:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c (x#(c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = x : listAdd c xs
PS: in case you wondered why I did not use your Int argument? Because I don't know what you want to do with it if there is already a value - here is a version where I just add it to it (seems resonable):
listAdd :: Char -> Int -> [(Char,Int)] -> [(Char,Int)]
listAdd c i [] = [(c,i)]
listAdd c i (x#(c',i'):xs)
| c' == c = (c,i+i'):xs
| otherwise = x : listAdd c i xs
List manipulations with just recursive functions can be indeed hard for beginners to grok, but in this case they should fit the problem nicely.
Let's start with a bit better signature and a helper.
type MyList = [(Char, Int)]
listAdd :: Char -> MyList -> MyList
listAdd p l = listAdd' p [] l
Notice that I've changed the signature to accept just Char; we don't need to supply the initial count, since if there are no such elements currently on the list, we'll just set it to 1 when adding a new element.
Okay, that's the basic skeleton. The helper is there just to make it easier to store the "already processed" part of the list. Let's look at it:
listAdd' :: Char -> MyList -> MyList -> MyList
First, we add the recursion end condition:
listAdd' p left [] = left ++ [(p, 1)]
This means that if we haven't found the element to replace earlier, we can just add it at the end.
listAdd' p left (x:right) = if p == fst x
then left ++ [(fst x, snd x + 1)] ++ right
else listAdd' p (left ++ [x]) right
Okay, so now we split up the "right" part to the first element of it and the rest. Let's look at the if:
if we managed to find the element, we can end the computation by appending the rest of the list to the modified element and what we had previously
if it's still not it, we proceed with recursion.
As an additional remark at the end, you could easily change Char to Eq a => a to allow your function to work on any type that can be directly compared, Char included.
I have 2 lists which I am trying to fill will items. While reading from stdin, depending on the value of one of the things read, I want to append to a different list. Example,
import Control.Monad(replicateM)
main = do
n <- getLine
let l1 = [], l2 = []
in replicateM (read n) (getLine >>= (\line ->
case line of "Yes" ->
-- do something with line
-- and append value of that thing to l1
"No" ->
-- do something else
-- append this value to l2
putStrLn line))
I realise the above code has syntax errors and such, but hopefully you can see what I am trying to and suggest something.
This is the answer I came up with
While we are at it, can someone explain why this gives me an infinite list:
let g = []
let g = 1:g
-- g now contains an infinite list of 1's
This is what I finally came up with:
import Control.Monad(replicateM)
import Data.Either
getEither::[String] -> [Either Double Double]
getEither [] = []
getEither (line:rest) = let [n, h] = words line
fn = read f :: Double
e = case heist of "Yes" -> Left fn
"No" -> Right fn
in e : getEither rest
main = do
n <- getLine
lines <- replicateM (read n) getLine
let tup = partitionEithers $ getEither lines :: ([Double], [Double])
print tup
Not sure how fmap could have been used in this instance
Here is a short ghci session that may give you some ideas:
> :m + Control.Monad Data.Either
> partitionEithers <$> replicateM 3 readLn :: IO ([Int], [Bool])
Left 5
Right True
Left 7
([5,7],[True])
The answer to your second question is that let is recursive; so the two gs in let g = 1:g are referring to the same in-memory object.
You are thinking in term of mutable variables: you are "initializing" l1,l2 to the empty list and then reasoning about updating them with longer lists. This design works fine in imperative programming, but not so simply in pure functional programming since it involves mutation.
Now, even in pure functional programming we have ways to simulate mutation, through monads. For instance, once can achieve mutation here through IORefs or StateT IO. In this case, though, is would be an unnecessarily complex way to solve the task.
You want to append data to form two lists. You want to use replicateM, which is fine. The point is that replicateM will build just one list, instead of two. The question now is: how can we create a list which is easily split into two?
A first ugly attempt is to generate a list of tagged values, i.e. a list of pairs:
case line of
"Yes" -> let value = ... in
return ("for l1", value)
"No" -> let value = ... in
return ("for l2", value)
Doing this would make replicateM produce a list such as
[("for l1", value1), ("for l1", value2), ("for l2", value3), ...]
which we can then split into two lists.
The use of strings for tags looks however a bit unelegant, since a boolean would suffice:
case line of
"Yes" -> let value = ... in
return (True, value)
"No" -> let value = ... in
return (False, value)
An even better approach would be to use the Either a b type:
case line of
"Yes" -> let value1 = ... in
return (Left value1)
"No" -> let value2 = ... in
return (Right value2)
The nice consequence of the above is that value1 and value2 can even be of different types. The previous snippets forced them to share their type: since we build a list of pairs each pair must have the same type. The new list is now instead of type [Either a b] where a is the type of values to be put in l1, and b that for l2.
Once you get a [Either a b] you want to split it in [a] and [b]. As #DanielWagner suggests in his answer, you can exploit partitionEithers for this.
I am trying to find the length of a list in ocaml.
I call a function first called
> let get_list_length e in
> print_list_length out x
the actual code in get_list_length is where I am confused. The "e" is a list of "commands" and I want to find the length of all the "commands".
let get_list_length(e:values) : unit =
match e with
let x =
list.length(e);;
So my e is the list of "commands" which are a bunch of values specified in my grammar file. I am confused about how to get the length of the list since e is a list of values and I want the length of that list.
Any help would be appreciated.
To get the length of a list is simple:
List.length my_list
Your get_list_length function can be as simple as:
let get_list_length e = List.length e
or more simply:
let get_list_length = List.length
As you currently have defined it, get_list_length returns type unit so you won't get anything useful from it. You are also using match incorrectly, it's usually used like this:
match e with something -> do something
| something_else -> do something_else