I'm learning ocaml and I'm trying to write easy function which prints out firsts given as argument int's.
What I have wrote:
let rec take(number, lista)=
let rec take_acc(number, lista, acc)=
match number with
| 0 -> []
| number < 0 -> []
| number > lista.length -> lista
| number < lista.length -> take_acc(number-1, lista.tl, acc#lista.head);;
take_acc(number, lista, [])
let listas = 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: [];;
take(2,listas);;
The point is, that given code above gives me error:
Error: Unbound value take
What I'm doing wrong?
The point is that this code works:
let xxl = 11 :: 33 :: 54 :: 74 :: [];;
let rec take2 (ile,xxx) =
if ile=0 || ile<0 then []
else
if ile>(List.length xxl) then take2(ile-1,xxx)
else
List.hd xxx :: take2(ile-1,List.tl xxx);;
Where is difference beetwen these two programs?
EDIT:
Due to Jeffrey Scofield's suggestion I have written something like this:
let rec take2(ilosc, lista) =
let rec take_acc(ilosc, lista, acc) =
if ilosc = 0 || ilosc < 0 then []
else
if ilosc > List.length lista
then lista
else
take_acc(ilosc-1, lista.tl, acc#lista.hd);;
let listas = 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: [];;
take2(2,listas);;
Still the same.
Your code is not syntactically well formed. So it couldn't ever reach the point of saying that take isn't defined.
The first thing to fix is your use of patterns. The construct number < 0 isn't a pattern, it's a boolean expression. You can have a boolean as part of a pattern using when:
| _ when number < 0
However, this isn't particulary good style for what you want to test. It might be better just to use if for your tests.
The next thing to fix might be your use of lista.length. The way to get the length of a list in OCaml is List.length lista.
Related
I´m new to Haskell.
Let´s say I want to sum up the first n elements of a list with a generated function on my own. I don´t know how to do this with Haskell. I just know how to sum up a whole given list, e.g.
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
In order to sum up the first n elements of a list, for example
take the first 5 numbers from [1..10], which is 1+2+3+4+5 = 15
I thought I could do something like this:
sumList :: Int -> [Int] -> Int
sumList take [] = 0
sumList take (x:xs) = x + take $ sumList xs
But it doesn´t work... What´s wrong?
So you know how to sum up the numbers in a list,
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
and if that list has no more than 5 elements in it, this function will even return the correct result if you indeed intended to sum no more than 5 elements in an argument list. Let's make our expectations explicit by renaming this function,
sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements [] = 0
sumUpToFiveElements (x:xs) = x + sumUpToFiveElements xs
it won't return the correct result for lists longer than five, but at least the name is right.
Can we fix that? Can we count up to 5? Can we count up to 5 while also advancing along the input list as we do?
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
This still isn't right of course. We do now count, but for some reason we ignore the counter. What is the right time to react to the counter, if we want no more than 5 elements? Let's try counter == 5:
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5 [] = 0
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
But why do we demand the list to also be empty when 5 is reached? Let's not do that:
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5 _ = 0 -- the wildcard `_` matches *anything*
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
Success! We now stop counting when 5 is reached! More, we also stop the summation!!
Wait, but what was the initial value of counter? We didn't specify it, so it's easy for a user of our function (that would be ourselves) to err and use an incorrect initial value. And by the way, what is the correct initial value?
Okay, so let's do this:
sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements xs = go 1 xs -- is 1 the correct value here?
where
go counter _ | counter == 5 = 0
go counter [] = 0
go counter (x:xs) = x + go (counter + 1) xs
Now we don't have that extraneous argument that made our definition so brittle, so prone to a user error.
And now for the punchline:
Generalize! (by replacing an example value with a symbolic one; changing 5 to n).
sumUpToNElements :: Int -> [Int] -> Int
sumUpToNElements n xs = .......
........
Done.
One more word of advice: don't use $ while at the very beginning of your learning Haskell. Use explicit parens.
sumList take (x:xs) = x + take $ sumList xs
is parsed as
sumList take (x:xs) = (x + take) (sumList xs)
This adds together two unrelated numbers, and then uses the result as a function to be called with (sumList xs) as an argument (in other words it's an error).
You probably wouldn't write it that way if you were using explicit parens.
Well you should limit the number of values with a parameter (preferably not take, since
that is a function from the Prelude), and thus limit the numbers.
This limiting in your code is apparently take $ sumList xs which is very strange: in your function take is an Int, and $ will basically write your statement to (x + take) (sumList xs). You thus apparently want to perform a function application with (x + take) (an Int) as function, and sumList xs as argument. But an Int is not a function, so it does not typecheck, nor does it include any logic to limit the numbers.
So basically we should consider three cases:
the empty list in which case the sum is 0;
the number of elements to take is less than or equal to zero, in that case the sum is 0; and
the number of elements to take is greater than 0, in that case we add the head to the sum of taking one element less from the tail.
So a straightforward mapping is:
sumTakeList :: (Integral i, Num n) => i -> [n] -> n
sumTakeList _ [] = 0
sumTakeList t (x:xs) | t <= 0 = 0
| otherwise = x + sumTakeList (t-1) xs
But you do not need to write such logic yourself, you can combine the take :: Int -> [a] -> [a] builtin with the sum :: Num a => [a] -> a functions:
sumTakeList :: Num n => Int -> [n] -> n
sumTakeList t = sum . take t
Now if you need to sum the first five elements, we can make that a special case:
subList5 :: Num n => [n] -> n
sumList5 = sumTakeList 5
A great resource to see what functions are available and how they work is Hoogle. Here is its page on take and the documentation for the function you want.
As you can see, the name take is taken, but it is a function you can use to implement this.
Note that your sumList needs another argument, the number of elements to sum. the syntax you want is something like:
sumList :: Int -> [Int] -> Int
sumList n xs = _ $ take n xs
Where the _ are blanks you can fill in yourself. It's a function in the Prelude, but the type signature is a little too complicated to get into right now.
Or you could write it recursively, with two base cases and a third accumulating parameter (by means of a helper function):
sumList :: Int -> [Int] -> Int
sumList n xs = sumList' n xs 0 where
sumList' :: Int -> [Int] -> Int -> Int
sumList' 0 _ a = _ -- A base case.
sumList' _ [] a = _ -- The other base case.
sumList' m (y:ys) a = sumList' _ _ _ -- The recursive case.
Here, the _ symbols on the left of the equals signs should stay there, and mean that the pattern guard ignores that parameter, but the _ symbols on the right are blanks for you to fill in yourself. Again, GHC will tell you the type you need to fill the holes with.
This kind of tail-recursive function is a very common pattern in Haskell; you want to make sure that each recursive call brings you one step closer to the base case. Often, that will mean calling itself with 1 subtracted from a count parameter, or calling itself with the tail of the list parameter as the new list parameter. here, you want to do both. Don't forget to update your running sum, a, when you have the function call itself recursively.
Here's a short-but-sweet answer. You're really close. Consider the following:
The take parameter tells you how many elements you need to sum up, so if you do sumList 0 anything you should always get 0 since you take no elements.
If you want the first n elements, you add the first element to your total and compute the sum of the next n-1 elements.
sumList 0 anything = 0
sumList n [] = 0
sumList n (e:es) = e + sumList (n-1) e
I have a following problem. From a list, I must separate mod 3 = 0 element, mod 3 = 1 element and mod 3 = 2 element to 3 different lists and return list of these 3 lists. My question is pretty obvious - how do I do that? Is there some kind of simple rule to this I'm missing?
What I have so far is not much but there you go:
let separate xs =
let rec help xs i =
match xs i with
| [] _ -> []
| hd a -> if a mod 3 = 0 //HOW DO I RETURN
else if a mod 3 = 1
else
UPDATED:
Finished code:
let separate xs =
let rec help (list, i, xs1, xs2, xs3) =
match list with
| [] -> [xs1;xs2;xs3]
| head :: tail -> (if i mod 3 = 0 then help (tail, i+1, head::xs1, xs2, xs3)
else if i mod 3 = 1 then help (tail, i+1, xs1, head::xs2, xs3)
else help (tail, i+1, xs1, xs2, head::xs3))
in help (xs, 0, [], [], []);;
You'll need to accumulate the partial results in lists, and then return those lists :
let split_by_mod_3 l =
let rec aux l mod0 mod1 mod2 = match l with
| [] -> [mod0; mod1; mod2]
| hd::tail when hd mod 3 == 0 -> aux tail (hd::mod0) mod1 mod2
| hd::tail when hd mod 3 == 1 -> aux tail mod0 (hd::mod1) mod2
| hd::tail when hd mod 3 == 2 -> aux tail mod0 mod1 (hd::mod2)
in
aux l [] [] [];;
A usual way is to use List.fold* function, that generalizes an idea of list iteration. But, in your case, it may not be appropriate (depending on what your teachers are asking).
You can iterate over your list maintaining some notion of state (indeed, you need three extra "variables" for three different lists). Here is a pattern for iterating over lists
let my_function lst =
let rec loop acc lst = match lst with
| [] -> <do_some_post_iteration_work> acc
| head :: rest ->
let result = <do_something_with_nth_element> head in
let accum = <add_result_to_accumulator> result acc in
loop accum rest in
let accum = <initialize_accumulator> in
loop accum lst
I used long names so that you can understand the meaning without extra comments, although you're welcome to ask. Also, keep in mind, that your state (aka accumulator), can be also a value of any type. Using a triple would be a not a bad idea in your case.
I am absolute OCaml beginner and have an assignment about more code. I have got the following code, but I don't know how it works. If someone can help me out, I appreciate it.
# let explode str = (*defines function that explodes argument str witch is type
string into list of chars*)
let rec exp = function (*defines recursive function exp*)
| a, b when a < 0 -> b (*this part i dont know.is this pattern
matching ?is it function with arguments a and b
and they go into expression? when is a guard and
then we have if a is smaller than 0 then b *)
(*if a is not smaller than 0 then this function ? *)
| a, b -> exp (a-1, str.[a]::b) (*this i dont know, a and b are arguments
that go into recursive function in the way
that a is decreesed by one and b goes into
string a?? *)
in
exp ((String.length str)-1, []);; (*defined function exp on string lenght of
str decresed by one (why?) [ ]these
brackets mean or tell some kind of type ? *)
# let split lst ch =
let rec split = function (* defines recursive fun split *)
| [], ch, cacc', aacc' -> cacc'::aacc'(* if empty ...this is about what i got
so far :) *)
| c::lst, ch, cacc', aacc' when c = ch -> split (lst, ch, [], cacc'::aacc')
| c::lst, ch, cacc', aacc' -> split (lst, ch, c::cacc', aacc')
in
split (lst, ch, [], []);;
val split : 'a list -> 'a -> 'a list list = <fun>
This code is ugly. Whoever has been giving that to you is making you a disservice. If a student of mine wrote that, I would ask them to rewrite them without using when conditionals, because they tend to be confusing, encourage to write pattern-matching-heavy code at places where they are not warranted.
As a rule of the thumb, beginners should never use when. A simple if..then..else test provides an increase in readability.
Here are equivalent versions of those two functions, rewritten for readability:
let explode str =
let rec exp a b =
if a < 0 then b
else exp (a - 1) (str.[a] :: b)
in
exp (String.length str - 1) []
let split input delim_char =
let rec split input curr_word past_words =
match input with
| [] -> curr_word :: past_words
| c :: rest ->
if c = delim_char
then split rest [] (curr_word :: past_words)
else split rest (c :: curr_word) past_words
in
split input [] []
My advice to understand them is to run them yourself, on a given example, on paper. Just write down the function call (eg. explode "foo" and split 'b' ['a';'b';'c';'d']), expand the definition, evaluate the code to get another expression, etc., until you get to the result. Here is an example:
explode "fo"
=>
exp (String.length "fo" - 1) []
=>
exp 1 []
=>
if 1 < 0 then [] else exp 0 ("fo".[1] :: [])
=>
exp 0 ("fo".[1] :: [])
=>
exp 0 ('o' :: [])
=>
exp 0 ['o']
=>
if 0 < 0 then ['o'] else exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ('f' :: ['o'])
=>
exp (-1) ['f'; 'o']
=>
if -1 < 0 then ['f'; 'o'] else exp (-2) ("fo".[-1] :: ['o'])
=>
['f'; 'o']
Take the care to do that, for each function, and any function you will have problem understanding. On a small example. That's the best way to get a global view of what's going on.
(Later when you grow more used to recursion, you'll find out that you don't actually need to do that, you can reason inductively on the function: make an assumption on what they do, and assuming that recursive calls actually do that, check that it indeed does it. In more advanced cases, trying to hold all the execution in one's head is just too hard, and this induction technique works better, but it is more high-level and requires more practices. First begin by simply running the code.)
If you're using the Core library you can just use
String.to_list "BKMGTPEZY"
Which will return a list of chars if you want strings just map it:
String.to_list "BKMGTPEZY" |> List.map ~f:Char.to_string
Outputs:
- : bytes list = ["B"; "K"; "M"; "G"; "T"; "P"; "E"; "Z"; "Y"]
As a function
let explode s = String.to_list s |> List.map ~f:Char.to_string
You can also implement in this way.
let rec strexp s =
if length(s)==0 then
[]
else
(strexp (sub s 0 (length(s)-1)))#(s.[length(s)-1]::[])
;;
I would like to print some rectangles one by one in a terminal like that:
4 5 7 8
2 5
3 : bool 6 : int
Which represents that, given an array a, the zone from a([2,3], [4,5]) is bool and the zone from a([5,6], [7,8]) is int.
So the key is to print a block of data in several rows, instead of 1 row as default. Does anyone know how to realize that in Ocaml?
Thank you very much!
Basically, there are two approaches possible:
accumulate your two-dimensional output and use a specialized print function which rearranges the strings in a way you wish
print to a medium with 2D capabilities like terminal or GUI element (to play with terminal screen, one can use a binding to ncurses)
The first approach is more universal and remains functional in spirit. For example:
let item1 =
[" 4 5 "
;"2 "
;"3 : bool "
]
let item2 =
[" 7 8 "
;"5 "
;"6 : int "
]
let transpose ll =
let rec pick_one ll =
match ll with
| [] -> []
| [] :: _ -> []
| _ ->
let tear (reaped, rest) l =
match l with
| [] -> assert false
| hd :: tl -> (hd :: reaped, tl :: rest)
in
let (reaped, rest) = List.fold_left tear ([], []) ll in
(reaped :: (pick_one rest))
in
pick_one ll
let multiline_print items =
let by_lines = transpose items in
let show_line line = List.iter print_string line; print_endline "" in
List.iter show_line by_lines
let _ = multiline_print [item1; item2]
Depending on your needs, you may build printf-like functionality around this.
You need to route through a "layout engine" the strings produced by the functions in your new Printf-like module.
i'm trying to learn ocaml right now and wanted to start with a little program, generating all bit-combinations:
["0","0","0"]
["0","0","1"]
["0","1","0"]
... and so on
My idea is the following code:
let rec bitstr length list =
if length = 0 then
list
else begin
bitstr (length-1)("0"::list);
bitstr (length-1)("1"::list);
end;;
But i get the following error:
Warning S: this expression should have type unit.
val bitstr : int -> string list -> string list = <fun>
# bitstr 3 [];;
- : string list = ["1"; "1"; "1"]
I did not understand what to change, can you help me?
Best regards
Philipp
begin foo; bar end executes foo and throws the result away, then it executes bar. Since this makes only sense if foo has side-effects and no meaningful return value ocaml emits a warning if foo has a return value other than unit, since everything else is likely to be a programmer error (i.e. the programmer does not actually intend for the result to be discarded) - as is the case here.
In this case it really does make no sense to calculate the list with "0" and then throw it away. Presumably you want to concatenate the two lists instead. You can do this using the # operator:
let rec bitstr length list =
if length = 0 then
[list]
else
bitstr (length-1)("0"::list) # bitstr (length-1)("1"::list);;
Note that I also made the length = 0 case return [list] instead of just list so the result is a list of lists instead of a flat list.
Although sepp2k's answer is spot on, I would like to add the following alternative (which doesn't match the signature you proposed, but actually does what you want) :
let rec bitstr = function
0 -> [[]]
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in
(f "0" l)#(f "1" l);;
The first difference is that you do not need to pass an empty list to call the function bitsr 2 returns [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Second, it returns a list of ordered binary values. But more importantly, in my opinion, it is closer to the spirit of ocaml.
I like to get other ideas!
So here it is...
let rec gen_x acc e1 e2 n = match n with
| 0 -> acc
| n -> (
let l = List.map (fun x -> e1 :: x) acc in
let r = List.map (fun x -> e2 :: x) acc in
gen_x (l # r) e1 e2 (n - 1)
);;
let rec gen_string = gen_x [[]] "0" "1"
let rec gen_int = gen_x [[]] 0 1
gen_string 2
gen_int 2
Result:
[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]
[[0; 0]; [0; 1]; [1; 0]; [1; 1]]