I was wondering how I can update the value of a variable through the iteration of a list. For example, let's say I want to keep track of the number of variables of a list. I could do something like
let list = [1;2;3;4;5]
let length = 0 in
let getCount elmt =
length = length+1 in
List.iter getCount list
but I get the error This expression has type 'a -> bool which makes sense because at length = length+1 I am comparing using =. How should I update the value of length?
EDIT:
I tried
let wordMap =
let getCount word =
StringMap.add word (1000) wordMap in
List.fold_left getCount StringMap.empty wordlist;;
but it doesn't know what wordMap is in getCount function...
#PatJ gives a good discussion. But in real code you would just use a fold. The purpose of a fold is precisely what you ask for, to maintain some state (of any type you like) while traversing a list.
Learning to think in terms of folds is a basic skill in functional programming, so it's worth learning.
Once you're good at folds, you can decide on a case-by-case basis whether you need mutable state. In almost all cases you don't.
(You can definitely use a fold to accumulate a map while traversing a list.)
You have several ways to do this.
The simpler way (often preferred by beginners coming from the imperative world) is to use a reference. A reference is a variable you can legally mutate.
let length l =
let count = ref 0 in
let getCount _ = (* _ means we ignore the argument *)
count := !count + 1
in
List.iter getCount l;
!count
As you can see in here, !count returns the value currently in the reference and := allows you to do the imperative update.
But you should not write that code
Yeah, I'm using bold, this is how serious I am about it. Basically, you should avoid using references when you can rely on pure functional programing. That is, when there are no side-effects.
So how do you modify a variable when you are not allowed to? That's where recursion comes in. Check this:
let rec length l =
match l with
| [] -> 0
| _::tl -> 1 + length tl
In that code, we no longer have a count variable. Don't worry, we'll get it back soon. But you can see that just by calling length again, we can assign a new value tl to the argument l. Yet it is pure and considered a better practice.
Well, almost.
The last code has the problem of recursion: each call will add (useless) data to the stack and, after being through the list, will do the additions. We don't want that.
However, function calls can be optimized if they are tail calls. As Wikipedia can explain to you:
a tail call is a subroutine call performed as the final action of a
procedure.
In the later code, the recursive call to length isn't a tail call as + is the final action of the function. The usual trick is to use an accumulator to store the intermediate results. Let's call it count.
let rec length_iterator count l =
match l with
| [] -> count
| _::tl -> length_iterator (count+1) tl
in
let length l = length_iterator 0 l
And now we have a neat, pure, and easy-to-optimize code that calculates the length of your list.
So, to answer the question as stated in the title: iterate with a (tail-)recursive function and have the updatable variables as arguments of this function.
If the goal is to get the length of the list, just use the function provided by List Module: List.length. Otherwise, variables in OCaml are never mutable and what you're trying to do is illegal in OCaml and not functional at all. But if you really have to update a value, consider using ref(for more info: http://www.cs.cornell.edu/courses/cs3110/2011sp/recitations/rec10.htm).
Related
I'm trying to implement a simple Stack but I'm confused as to why I get an infinite list when I push an integer to the stack.
All of the other functions work as I expect them but I don't understand the problem with push. It goes wrong when I try to assign an empty stack to itself that has pushed a variable like the following:
λ > a = makeStack
λ > push 3 a
[3]
λ > a
[]
λ > a = push 3 a
λ > a
[3,3,3,3,3,3,3,3,3,3^CInterrupted.
type Stack a = [a]
makeStack :: Stack a
makeStack = []
push :: a -> Stack a -> Stack a
push a as = (a:as)
Haskell does not allow mutation. In a source file, if you define a variable a and then attempt to reassign it, as you do here with a = push 3 a, you would get a compilation error. The only reason you don't is that you are working in GHCi, which does allow you to redefine variables - this is purely a convenience so you don't have to keep on thinking up new names while experimenting with different definitions.
And, crucially, a = push 3 a is not giving a new value to a based on the previous one, as it would be in an imperative language. Instead, it is a definition of a in terms of itself.
That's why you get an infinite list - your definition is processed as follows:
a = push 3 a
= 3:a
= 3:(push 3 a)
= 3:(3:a)
and so on. Because of Haskell's laziness, there's no problem with a definition like this - GHCi will, when you ask for the full list, as here, simply calculate one element at a time, and therefore keep printing 3s until you tell it to stop.
To get what you want, you need to either just type push 3 a, or if you need to assign it a name, simply choose a different name from a. b = push 3 a followed by b will behave as you expect.
There are (I guess, almost) no mutable (thanks to #amalloy for correcting my terminology) variables in haskell.
If you write something like this:
x = f x
It enters an infinite loop: f (f (f ...
So, there is no past value of a in which 3 may be pushed.
Therefore, you have to put push 3 a in some other value (or directly into the ghci for that matter).
Such a loop might come in handy sometimes though. Take a look at Data.Function.fix:
fix :: (a -> a) -> a
fix f = let x = f x in x
It can be used to do the same thing as you do:
GHCi> fix (push 3)
[3,3,3,3,^CInterrupted.
Yet, the infinite loop is not always the case. Take a look:
factFun rec n = if n == 0 then 1 else n * rec (n - 1)
This function might look like factorial, yet the recursive call in the non-terminating branch is replaced with a dummy (rec). We would like to have this dummy replaced with factFun over and over and over again to get the factorial. fix does this:
GHCi> fix factFun 4
24
Note: I will duplicate my comment here: if the reader does not know of fix yet, I want to invite them on a long and interesting trip. I suggest they start with this wikibook on denotational semantics.
My question is probably digging a bit into the question on how smart the F# compiler really is.
I have a type module that scans a configuration file and should then provide a range of IP addresses between a start and an end address.
type IpRange (config: string) =
// Parse the config
member __.StartIp = new MyIp(startIp)
member __.EndIp = new MyIp(endIp)
Now I wanted to add the actual range giving me all IPs so I added
member __.Range =
let result = new List<MyIp>()
let mutable ipRunner = __.StartIp
while ipRunner <= __.EndIp do
result.Add(new MyIp(ipRunner))
ipRunner <- (ipRunner + 1)
result
which works but is not really idiomatic F#.
I then dug into the issue and came up with the following two alternatives
let rec GetIpRangeRec (startIp: MyIp) (endIp: MyIp) (ipList: MyIp list) =
if startIp <= endIp then
GetIpRangeRec (startIp + 1) endIp (ipList#[startIp])
else
ipList
and
let GetIpRangeUnfold (startIp: MyIp) (endIp: MyIp) =
startIp |> Seq.unfold(fun currentIp ->
if (currentIp <= endIp) then
Some(currentIp, currentIp + 1)
else
None)
As far as I have understood from reading up on lists and sequences, none is cached. So all three solutions would re-evalute the code to create a list whenever I try to access an item or enumerate the list.
I could solve this problem by using Seq.cache (and a previous cast to sequence where required) resulting in something like
member __.Range =
GetIpRangeRec startIp endIp []
|> List.toSeq
|> Seq.cache
but is this really necessary?
I have the feeling that I missed something and the F# compiler actually does cache the result without explicitely telling it to.
Lists are (normally at least, I suppose there might be some weird edge case I don't know about) stored directly as their values. Thus, your recursive function would specifically produce a list of MyIps - these would only be re-evaluated if you have done some weird thing where a MyIp is re-evaluated each time it is accessed. As in, when the function returns you'll have a fully evaluated list of MyIps.
There is one slight issue, however, in that your function as implemented isn't particularly efficient. Instead, I would recommend doing it in this slightly alternative way:
let rec GetIpRangeRec (startIp: MyIp) (endIp: MyIp) (ipList: MyIp list) =
if startIp <= endIp then
GetIpRangeRec (startIp + 1) endIp (startIp :: ipList)
else
List.rev ipList
Basically, the issue is that every time you use the # operator to append to the end of a list, the runtime has to walk to the end of the list to do the append. This means that you'll end up iterating over the list a whole bunch of times. Instead, better simply to prepend (i.e. append, but to the front), and then reverse the list just before you return it. This means that you only have to walk the list once, as prepending is always a constant-time operation (you just create a new list entry with a pointer to the previous front of the list).
Actually, since you probably don't want to use a pre-supplied list outside of your function, I would recommend doing it this way instead:
let GetIpRange startIp endIp =
let rec GetIpRangeRec (start: MyIp) (end: MyIp) (ipList: MyIp list) =
if start <= end then
GetIpRangeRec (start + 1) end (start :: ipList)
else
List.rev ipList
GetIpRangeRec startIp endIp List.empty
(note that I haven't tested this, so it may not work totally perfectly). If you do want to be able to pre-supply a starting list, then you can just stick with the first one.
Also, bear in mind that while lists are usually fine for sequential access, they're terrible for random accesses. If you need to be doing random lookups into the list, then I would recommend using a call to List.toArray once you get the complete list back. Probably no need to bother if you'll just be iterating over it sequentially though.
I'll make one more point though: From a total functional programming 'purist's' perspective your first implementation may not be totally 'functional', but the only mutability involved is all hidden away inside the function. That is, you're not mutating anything that is passed in to the function. This is perfectly fine from a functional purity perspective and might be good for performance. Remember that F# is functional-first, not zealously fuctional-only ;)
EDIT: Just thought of one more thing I would like to add: I don't know exactly how your MyIp types are constructed, but if you can build them out of numbers, it might be worth looking at using a sequence comprehension like seq {1 .. 100} and then piping that to a map to create the MyIps, e.g. seq {1 .. 100} |> Seq.map makeIp |> Seq.toList. This would be the easiest way, but would only work if you can simply specify a simple number range.
Seq is lazy in F#, ie there are benefits to caching the results occassionally. F# List is not lazy, it's an immutable single linked list that won't get any benefits from caching.
I'm trying to create a list of unique by appending to a list, but I'm getting this error.
Error: This expression has type 'a list
but an expression was expected of type unit
in_list is a boolean function that checks whether the value is in the list.
if(in_list x seen_list) then print_string("Already found") else seen_list#x in
List.iter uniq check_list;;
It seems like there must be some small syntactic error I need to fix for the append function. Suggestions?
TL;DR: Lists are immutable in OCaml
According to your code, you seem to believe that lists are mutable in OCaml, and they are not. Hence seen_list#x compute a new list but does not change seen_list.
You could change your code to
let uniq seen_list x =
if in_list x seen_list then
(Printf.printf: "uniq: %d: Already seen.\n" x; seen_list)
else x :: seen_list
in
List.fold_left uniq [] check_list
The uniq function maps a list of integers to a list of integers without repetitions, logging the entries it skips.
This code is obviously intended to be learning material, I guess, nevertheless you should be aware that it most likely implements a Shlemiel the painter's algorithm.
This is a type error, not a syntactic error.
An OCaml function must always return a result of the same type. Right now, when the item is in the list your function tries to return a different type than if the item is not in the list.
Specifically, when the item is already there your function calls print_string, which returns (). This is called unit, and is a placeholder representing no interesting value. When the item isn't already there, your function returns a value of type 'a list. Almost certainly what you need to do is to return a list in all cases.
It's hard to say more without seeing more of your code, but the most usual way to handle this situation is to return the old list when the item is already there and a new, longer list when the item isn't already there.
Update
There are many things to fix in this code, but that's the point of the exercise I assume.
Your next problem seems to be that List.iter is an imperative function, i.e., it wants to do something rather than produce a result. Hence the function that it iterates over the list should return unit (described above). You're using the function uniq instead, which returns a list.
If you want to use a higher-order function like List.iter, which is excellent OCaml style, you will need to use a fold (List.fold_left or List.fold_right), whose purpose is to accumulate a result.
Want to print list without using sequence operator:-
This is my program, I want to make this program without ";" operator and without using "let" for assigning variables !
let rec print_row = function
[]->()
|h::t -> print_int h; Printf.printf(" "); print_row t;;
You want to implement a generic approach for applying functions over any type of lists. You can go about this in the following manner using List.map:
print_string (String.concat " " (List.map string_of_int [1;2;3;4]));;
You can learn more about List.map here
This looks like a school assignment, so I'll just make some suggestions.
If you're trying to reformulate the function into more idiomatic OCaml, one thing to think of is the functions in the List module. In particular, you could write a function that does what you want to do for each element of the list, then look in the List module for a way to call a function for every element of a list.
If you just want to eliminate the ; operator (which is pretty unlikely I realize), you can always rewrite a; b as let _ = a in b.
I'm a newbie to Haskell, I have a problem. I need to write a function that splits a list into a list of lists everywhere a 'separation' appears.
I will try to help you develop the understanding of how to develop functions that work on lists via recursion. It is helpful to learn how to do it first in a 'low-level' way so you can understand better what's happening in the 'high-level' ways that are more common in real code.
First, you must think about the nature of the type of data that you want to work with. The list is in some sense the canonical example of a recursively-defined type in Haskell: a list is either the empty list [] or it is some list element a combined with a list via a : list. Those are the only two possibilities. We call the empty list the base case because it is the one that does not refer to itself in its definition. If there were no base case, recursion would never "bottom out" and would continue indefinitely!
The fact that there are two cases in the definition of a list means that you must consider two cases in the definition of a function that works with lists. The canonical way to consider multiple cases in Haskell is pattern matching. Haskell syntax provides a number of ways to do pattern matching, but I'll just use the basic case expression for now:
case xs of
[] -> ...
x:xs' -> ...
Those are the two cases one must consider for a list. The first matches the literal empty list constructor; the second matches the element-adding constructor : and also binds two variables, x and xs', to the first element in the list and the sublist containing the rest of the elements.
If your function was passed a list that matches the first case, then you know that either the initial list was empty or that you have completed the recursion on the list all the way past its last element. Either way, there is no more list to process; you are either finished (if your calls were tail-recursive) or you need to pass the basic element of your answer construction back to the function that called this one (by returning it). In the case that your answer will be a list, the basic element will usually be the empty list again [].
If your function was passed a list that matches the second case, then you know that it was passed a non-empty list, and furthermore you have a couple of new variables bound to useful values. Based on these variables, you need to decide two things:
How do I do one step of my algorithm on that one element, assuming I have the correct answer from performing it on the rest of the list?
How do I combine the results of that one step with the results of performing it on the rest of the list?
Once you've figured the answers to those questions, you need to construct an expression that combines them; getting the answer for the rest of the list is just a matter of invoking the recursive call on the rest of the list, and then you need to perform the step for the first element and the combining.
Here's a simple example that finds the length of a list
listLength :: [a] -> Int
listLength as =
case as of
[] -> 0 -- The empty list has a length of 0
a:as' -> 1 + listlength as' -- If not empty, the length is one more than the
-- length of the rest of the list
Here's another example that removes matching elements from a list
listFilter :: Int -> [Int] -> Int
listFilter x ns =
case ns of
[] -> [] -- base element to build the answer on
n:ns' -> if n == x
then listFilter x ns' -- don't include n in the result list
else n : (listFilter x ns') -- include n in the result list
Now, the question you asked is a little bit more difficult, as it involves a secondary 'list matching' recursion to identify the separator within the basic recursion on the list. It is sometimes helpful to add extra parameters to your recursive function in order to hold extra information about where you are at in the problem. It's also possible to pattern match on two parameters at the same time by putting them in a tuple:
case (xs, ys) of
([] , [] ) -> ...
(x:xs', [] ) -> ...
([] , y:ys') -> ...
(x:xs', y:ys') -> ...
Hopefully these hints will help you to make some progress on your problem!
Let's see if the problem can be reduced in a obvious way.
Suppose splitList is called with xs to split and ys as the separator. If xs is empty, the problem is the smallest, so what's the answer to that problem? It is important to have the right answer here, because the inductive solution depends on this decision. But we can make this decision later.
Ok, so for problem to be reducable, the list xs is not empty. So, it has at least a head element h and the smaller problem t, the tail of the list: you can match xs#(h:t). How to obtain the solution to the smaller problem? Well, splitList can solve that problem by the definition of the function. So now the trick is to figure out how to build the solution for bigger problem (h:t), when we know the solution to the smaller problem zs=splitList t ys. Here we know that zs is the list of lists, [[a]], and because t may have been the smallest problem, zs may well be the solution to the smallest problem. So, whatever you do with zs, it must be valid even for the solution to the smallest problem.
splitList [] ys = ... -- some constant is the solution to the smallest problem
splitList xs#(h:t) ys = let zs = splitList t ys
in ... -- build a solution to (h:t) from solution to t
I don't know how to test it. Anybody tells me how to write a function to a .hs file and use winGHCi to run this function?
WinGHCi automatically associates with .hs files so just double-click on the file and ghci should start up. After making some changes to the file using your favourite editor you can write use the :r command in ghci to reload the file.
To test the program after fixing typos, type-errors, and ensuring correct indentation, try calling functions you have defined with different inputs (or use QuickCheck). Note Maybe is defined as Just x or Nothing. You can use fromMaybe to extract x (and provide default value for the Nothing case).
Also try to make sure that pattern matching is exhaustive.