I just start learning haskell and pattern matching. I just don't understand how it implemented, is the [] and (x:_) evaluates to the different type and the function implementations for this pattern recognized because of polymorphism, or I just wrong and there is another technique used.
head' :: [a] -> a
head' [] = error "Can't call head on an empty list, dummy!"
head' (x:_) = x
Or lets consider this pattern matching function:
tell :: (Show a) => [a] -> String
tell [] = "The list is empty"
tell (x:[]) = "The list has one element: " ++ show x
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y
tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y
I think I wrong because each list with different number of elements can't have deferent type. Can you explain me how haskell knows which pattern is correct for some function implementation? I understand how it works logically but not deep. Explain it to me please.
There's a bit of a level of indirection between the syntax in Haskell and the implementation at runtime. The list syntax that you see in most source is actually a bit of sugar for what is actually a fairly regular data type. The following two lines are equivalent:
data List a = Nil | Cons a (List a)
data [a] = [] | a : [a] -- pseudocode
So when you type in [a,b,c] this translates into the internal representation as (a : (b : (c : []))).
The pattern matching you'll see at the top level bindings in are also a bit of syntactic sugar ( sans some minor details ) for case statements which deconstruct the data types onto the right hand side of the case of the pattern match. The _ symbol is a builtin for the wildcard pattern which matches any expression ( so long as the pattern is well-typed ) but does add a variable to the RHS scope.
head :: [a] -> a
head x = case x of
(a : _) -> a
I think I wrong because each list with different number of elements can't have deferent type. Can you explain me how haskell knows which pattern is correct for some function implementation?
So to answer your question [] and (x:_) are both of the same type (namely [a] or List a in our example above). The list datatype is also recursive so all recursive combinations of Cons'ing values of type a have the same type, namely [a].
When the compiler typechecks the case statement it runs along each of the LHS columns and ensures that all the types are equivalent or can be made equivalent using a process called unification. The same is done on the right hand side of the cases.
Haskell "knows" which pattern is correct by trying each branch sequentially and unpacking the matched value to see if it has the same number of cons elements as the pattern and then proceeding to the branch which does, or failing with a pattern match error if none match. The same process is done for any pattern matching on data types, not just lists.
There are two separate sets of checks:
in compile time (before the program is run) the compiler simply checks that the types of the cases conform to the function's signature and that the calls to the function conform to the function's signature.
In runtime, when we have access to the actual input, a similar, but different, set of checks is executed: these checks take the * actual* input (not its type) at hand and determine which of the cases matches it.
So, to answer your question: the decision is made in compile time where we have not only the type but also the actual value.
Related
For the next code I'm getting an error:
fun epoly(L:real list, x:real)=
= if L = [] then 0.0 else (epoly(tl(L:real list), x:real));;
Error:
stdIn:42.1-42.57 Error: operator and operand don't agree [equality type required]
operator domain: ''Z * ''Z
operand: real list * 'Y list
in expression:
L = nil
Since you're not actually asking a question, it is a little unclear what your intent is. Presumably this is attempted code that doesn't work and the accompanying error message, and the implicit question is "Why doesn't this code work? What am I doing wrong, and what can I do to improve it?" But really that's guesswork, and those are lazy questions, too.
Here's how your post could look like if my assumptions above are correct and you want positive feedback in the future:
I am trying to write a function that evaluates a polynomial with real coefficients L for the variable x.
It looks like:
fun epoly (L : real list, x : real) =
if L = [] then 0.0 else epoly(tl L, x)
Unfortunately I am getting a type error that I don't understand:
stdIn:1.35-1.91 Error: operator and operand don't agree [equality type required]
operator domain: ''Z * ''Z
operand: real list * 'Y list
in expression:
L = nil
What does this error mean, and if this is not the right way to evaluate a polynomial, then what would another way to accomplish the same thing look like?
The take-aways:
Write what your problem is, don't let others assume what your problem is. Making a question easily understood makes people want to answer your question, and describing your problem in words tells what you think is the problem, so that people don't try and answer the wrong question. In this case, your question could have been "Under what version of the Standard ML specification were reals removed as an eqtype?" and a sufficient answer would have been '97. But would you have been happy about that answer?
Once you know how to ask the right question, you can also better google around (e.g. search for: evaluate polynomial "standard ml"|sml) and find that there exists code from which you can let yourself inspire: here, here, here.
Format your code nicely and make sure it works. Use StackOverflow's Markdown to format your code nicely. The code that you posted contains artifacts from the interactive REPL (an extra =), so anyone who copy-pastes it into a REPL will get an error, will have to figure out where it occurred, fix it, and then start to think about what could be the problem, since you didn't say. A good rule is to test that the code you posted works by copy-pasting it once you've asked the question. One can easily forget to include a non-standard function.
An answer, assuming my rendition of your "question" somewhat lines up with your intent:
When you do if L = [] ... then you're using equality for lists of reals, which in turn relies on equality for reals, but reals can't be compared for equality. See the Q&A "Why can't I compare reals in Standard ML?" You can test if a list of reals is empty without comparing reals by doing e.g.:
fun epoly (L, x) =
if null L then 0.0 else epoly (tl L, x)
This is because the standard library function null uses pattern matching on lists but does not address the list's elements, whereas = assumes that elements may have to be compared. Even though that never happens in practice in the example L = [], this is still an error in the type system.
If you were comparing reals for equality, consider using an epsilon test. Besides that, consider using pattern matching instead of hd and tl because those functions can fail and crash because they're partial:
fun epoly ([], x) = 0.0
| epoly (c::cs, x) = epoly (cs, x)
All this function does is throw away its second argument x, traverse its first argument, c::cs, and do nothing with each coefficient c. Presumably, in order to evaluate a polynomial, you must do something to coefficient c and x before doing the same thing recursively on the remaining coefficients cs and x, and then somehow compose those.
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).
This is my simple OCaml code to print out a merged list.
let rec merge cmp x y = match x, y with
| [], l -> l
| l, [] -> l
| hx::tx, hy::ty ->
if cmp hx hy
then hx :: merge cmp tx (hy :: ty)
else hy :: merge cmp (hx :: tx) ty
let rec print_list = function
| [] -> ()
| e::l -> print_int e ; print_string " " ; print_list l
;;
print_list (merge ( <= ) [1;2;3] [4;5;6]) ;;
I copied the print_list function from Print a List in OCaml, but I had to add ';;' after the function's implementation in order to avoid this error message.
File "merge.ml", line 11, characters 47-57:
Error: This function has type int list -> unit
It is applied to too many arguments; maybe you forgot a `;'.
My question is why ';;' is needed for print_list while merge is not?
The ;; is, in essence, a way of marking the end of an expression. It's not necessary in source code (though you can use it if you like). It is useful in the toplevel (the OCaml REPL) to cause the evaluation of what you've typed so far. Without such a symbol, the toplevel has no way to know whether you're going to type more of the expression later.
In your case, it marks the end of the expression representing the body of the function print_list. Without this marker, the following symbols look like they're part of the same expression, which leads to a type error.
For top-level expressions in OCaml files, I prefer to write something like the following:
let () = print_list (merge ( <= ) [1;2;3] [4;5;6])
If you code this way you don't need to use the ;; token in your source files.
This is an expansion of Jeffrey's answer.
As you know, when doing language parsing, a program has to break the flow in manageable lexical elements, and expect these so called lexemes (or tokens) to follow certain syntactic rules, allowing to regroup lexemes in larger units of meaning.
In many languages, the largest syntactic element is the statement, which diversifies in instructions and definitions. In these same languages, the structure of the grammar requires a special lexeme to indicate the end of some of these units, usually either instructions or statements. Others use instead a lexeme to separate instructions (rather than end each of them), but it's basically the same idea.
In OCaml, the grammar follows patterns which, within the algorithm used to parse the language, permits to elide such instruction terminator (or separator) in various circumstances. The keyword let for instance, is always necessary to introduce a new definition. This can be used to detect the end of the preceding statement at the outermost level of program statements (the top level).
However, you can easily see the problem it induces: the interactive version of Ocaml always need the beginning of a new statement to be able to figure out the previous one, and a user would never be able to provide statements one by one! The ;; special token was thus defined(*) to indicate the end of a top level statement.
(*): I actually seem to recall that the token was originally in OCaml ancestors, but then made optional when OCaml was devised; however, don't quote me on that.
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.