I've dabbled with Haskell in the past, and recently got back into it seriously, and I'm reading real world haskell. Some of the examples they've shone, I've yet to understand. Such at this one:
myLength [] = 0
myLength (x:xs) = 1 + myLength (xs)
I don't see how this works, what is 1 really being added too? How is the recursion returning something that can be added to? I don't get it.
And here we have this one:
splitLines [] = []
splitLines cs =
let (pre, suf) = break isLineTerminator cs
in pre : case suf of
('\r':'\n':rest) -> splitLines rest
('\r':rest) -> splitLines rest
('\n':rest) -> splitLines rest
_ -> []
isLineTerminator c = c == '\r' || c == '\n'
How does this work, what is pre really being attached too? I don't see how the the result of the case expression is something that pre can be concatenated to. Maybe I just need someone to explain the evaluation of these functions in details. I must be missing something very vital.
Thanks in advance!
EDIT: I know, it was a copy-paste fail. Sorry.
EDIT 2: It seems my confusion was with what these functions were actually /returning/ I have it all worked out now. Thanks for the answers guys, it finally clicked! I appreciate it!
As for the first one, it's a very basic way of recursion. However, it seems to be missing a part:
myLength [] = 0
It works by scaling off one element at the time from the list and adding one to the result. To visualise, consider the call
myLength [1,2,3]
which will evaluate to:
1 + myLength [2,3]
1 + 1 + myLength [3]
1 + 1 + 1 + myLength []
1 + 1 + 1 + 0
which is 3.
As for the second one, well, you have already split the string at the next line break into two parts: pre and suf. Now, suf will start with either a \n, or a \r, or a \r\n. We want to remove these. So we use pattern matching. See how the rest variable is essentially the suf variable minus the initial line break character(s).
So we have pre, which is the first line, and rest, which is the rest of the text. So in order to continue splitting rest into lines we call splitLines on it recursively and concatenate the result to pre.
To visualize, say you have the string "foo\nbar\r\nbaz".
So, when calling, the result will be:
[ pre => foo, suf => \nbar\r\nbaz, rest => bar\r\n\baz ]
foo : splitLines bar\r\nbaz
then splitLines is called again, and the result is expanded into:
[ pre => bar, suf => \r\nbaz, rest = baz ]
foo : bar : splitLines baz
then once again:
[ pre => baz, suf => [], rest = [] ]
foo : bar : baz
which is the final result.
I think the definition of myLength misses the case where the list is empty:
myLength [] = 0
myLength (x:xs) = 1 + myLength (xs)
With this definition, the myLength of an empty list is 0. The (x:xs) patten unpacks a list into the first item, a, and a list with the rest of the items, xs. If the list has one item, then xs is an empty list, so the result is 1 + 0. And so on.
Recursion is easiest to understand when you look at the base case first, and then see how each level of recursion builds on the result. (The base case is the case where the function does not call itself. If a recursive function doesn't have a base case, the output will be infinite.)
In the second example, the base case (the last case in the case-statment) is also an empty list. So pre will always be appended to a list, which will yield a new, longer, list.
Re: myLength (x:xs) = 1 + myLength (xs) -- this is "half" of the definition of myLength, it says, by pattern match, that if the argument has a head and a tail, then the result is one more than the recursive tail call on the tail -- there needs to be another half to say that the result is 0 when the argument cannot match x:xs, i.e., when the argument is an empty list.
In the second case, the possibility of different patterns matching is just made a bit more epxlicit via case.
BTW, laziness is not a key issue here -- ML, with eager evaluation but pattern matching much like Haskell, would work very similarly. Looks like pattern matching is what you really need to brush up about.
First of all the first example should be like this (edit: it looks like you fixed it now):
myLength [] = 0
myLength (x:xs) = 1 + myLength (xs)
It works like this: say I give it a list with three items, it returns one plus the length of the tail (which is one plus the length of the tail (which is one plus the length of the tail, (which is [] at this point), which is 1), which is w), which is 3 (the final answer). Maybe nested parenthesis will help you understand it. ;-)
It is instructive to look at what the type signatures of the functions would be. They could be:
myLength :: [a] -> Int
In myLength, 1 is being added to the result of the recursive call to myLength, which is an Int, which in turn results in an Int.
splitLines :: [Char] -> [[Char]]
In splitLines, pre (a [Char]) is being prepended to the result of the case statement, which, from looking at the cases, is either the result of a recursive call to splitLines, which is [[Char]]; or an empty list. In both cases, prepending pre (a [Char]) will result in a [[Char]] in turn.
Related
in standard ML, is variable shadowing in general, and in particular, when pattern matching acceptable? For this toy example:
case xs of
[] => 0
| x::xs => x + sum xs
Is the following better style?
fun sum(xs) =
case xs of
[] => 0
| x::xs' => x + sum xs'
Without shadowing, one has to pick different names, which clutters the code, especially when nested patterns, let function bindings, and other language constructs are being used.
Thank you!
is variable shadowing good style?
No.
But also xs and xs' aren't good either: They have the same type so it is very easy to accidentally use one instead of the other. In your case this probably leads to infinite recursion and that gets detected soon enough. But in other cases it might lead to more subtle bugs. This advice is not particular to functional programming.
Edit: For totality I'm including molbdnilo's suggestion of y::ys:
fun sum xs =
case xs of
[] => 0
| y::ys => y + sum ys
An alternative is to only pattern match and bind the values you actually need. In your sum example you don't actually need the full input for anything other than splitting apart. So you might write it like
fun sum [] = 0
| sum (x::xs) = x + sum xs
Or with even more implicit pattern matching matching:
val sum = foldl op+ 0
Another example, Exercism's Bob exercise, can be solved by first sanitizing the input and then classifying it:
datatype diction = Yelling | Asking | YellingAsking | Whatever
fun strip message = ...
fun classify message = ...
fun answer diction = ...
val response = answer o classify o strip
Here the message of the function strip will contain unstripped whitespace and the message of the classify function won't. So instead of having multiple messages, one having whitespace and the other one not, you put them in separate scopes of functions that do separate things.
I'm brand new to SML/NJ and I'm trying to make a recursive function
that makes a listOfLists. Ex: listOf([1,2,3,4]) will output
[[1],[2],[3],[4]]. I've found a recursive merge in SML/NJ, and I'm
trying to use it as kind've an outline:
- fun merge(xs,nil) = xs
= | merge(nil,ys) = ys
= | merge(x::xs, y::ys) =
= if (x < y) then x::merge(xs, y::ys) else y::merge(x::xs,ys);
- fun listOf(xs) = xs
= | listOf(x::xs) = [x]::listOf(xs);
I'm trying to use pattern match and I'm a little confused on it. I'm
pretty sure x is the head and then xs is the tail, but I could be
wrong. So what I'm trying to do is use the head of the list, make it a
list, and then add it to the rest of the list. But when trying to do
this function, I get the error:
stdIn:15.19-15.34 Error: operator and operand don't agree [circularity]
operator domain: 'Z list * 'Z list list
operand: 'Z list * 'Z list
in expression:
(x :: nil) :: listOf xs
This error is foreign to me because I don't have really any experience
with sml/nj. How can I fix my listOf function?
You are fairly close. The problem is that in pattern-matching, a pattern like xs (just a variable) can match anything. The fact that you end it with s doesn't mean that the pattern can only match a tail of a list. Using s in that way is just a programmer convention in SML.
Thus, in your definition:
fun listOf(xs) = xs
| listOf(x::xs) = [x]::listOf(xs);
The first line tells SML to return all values unchanged, which is clearly not your intent. SML detects that this is inconsistent with the second line where you are trying to change a value after all.
You need to change that first line so that it doesn't match everything. Looking at that merge function as a template, you need something which matches a basis case. The natural basis case is nil (which can also be written as []). Note the role that nil plays in the definition of merge. If you use nil instead of xs for the pattern in the first line of your function definition, your second line does exactly what you want and the function will work as intended:
fun listOf(nil) = nil
| listOf(x::xs) = [x]::listOf(xs);
I have a project I am working on and I need to implement a histogram function in OCaml. I have to write a function that takes a list as an argument and returns a histogram, in the form of a list of tuples. It would look something like this:
histogram [1;2;3;1;1;3];;
[(1,3);(2,1);(3,2)]
I can't however get this to work. I feel like I am pretty close but I just need some help / guidance on how to finish the actual histogram function. So far I have made it check a list (nl) for anything that may already be in there. If it doesnt contain the number already I add it to the list. My problem is that I dont know how to recall the function once I have added it to the list. See my code for where the problem lies.
let check a ls = match (a,ls) with
|a,[] -> false
|a,xs -> if fst (hd xs) != a then check a (tl xs) else true
let rec count a ls = match ls with
|[] -> 0
|x::xs -> if x = a then 1 + count a xs else 0 + count a xs
let nl = []
let rec histo l = match l with
|[]-> []
|x::xs -> if check x nl then histo xs else nl # [(x,count x l)] *******
I need to re call histo where the ****** are. Any help at all will be really appreciated.
This is pretty clearly a school assignment, so I'll just give a few hints.
You seem to expect to modify nl in your histo function. But OCaml variables are immutable. The variable named nl in your code will always be bound to an empty list. This is usually the first thing to figure out in FP: how to work with immutable values.
As a hint, the essence is to pass values like nl as parameters of your function. A function's parameters can (of course) be different in different calls to the function.
I don't follow your code for when x appears in nl (check returns true). In this case you need to create a list with an incremented count. But your code just continues without doing anything in particular.
If you redefine histo to take all the required parameters, your unfinished case just needs to call histo with the right parameters.
toastedDeli, just a little advice about your function count. You can use more pattern matching:
let rec count a ls = match ls with
|[] -> 0
|x::xs when x=a -> 1 + count a xs
|_::xs -> count a xs
let rec count a = function
|[] -> 0
|x::xs when x=a -> 1 + count a xs
|_::xs -> count a xs
Define a function that, given a list L, an object x, and a positive
integer k, returns a copy of L with x inserted at the k-th position.
For example, if L is [a1, a2, a3] and k=2, then [a1, x, a2, a3] is
returned. If the length of L is less than k, insert at the end. For
this kind of problems, you are supposed not to use, for example, the
length function. Think about how the function computes the length. No
'if-then-else' or any auxiliary function.
I've figured out how to make a function to find the length of a list
fun mylength ([]) = 0
| mylength (x::xs) = 1+ mylength(xs)
But, as the questions states, I can't use this as an auxiliary function in the insert function. Also, i'm lost as to how to go about the insert function? Any help or guidance would be appreciated!
Here's how to do this. Each recursive call you pass to the function tail of the list and (k - 1) - position of the new element in the tail of the list. When the list is empty, you construct a single-element list (which was given to you); when k is 0, you append your element to what's left from the list. On the way back, you append all heads of the list that you unwrapped before.
fun kinsert [] x k = [x]
| kinsert ls x 0 = x::ls
| kinsert (l::ls) x k = l::(kinsert ls x (k - 1))
I used a 0-indexed list; if you want 1-indexed, just replace 0 with 1.
As you can see, it's almost the same as your mylength function. The difference is that there are two base cases for recursion and your operation on the way back is not +, but ::.
Edit
You can call it like this
kinsert [1,2,3,4,5,6] 10 3;
It has 3 arguments; unlike your length function, it does not wrap arguments in a tuple.
Here's how I'd approach it. The following assumes that the list item starts from zero.
fun mylength (lst,obj,pos) =
case (lst,obj,pos) of
([],ob,po)=>[ob]
| (xs::ys,ob,0) => ob::lst
| (xs::ys,ob,po) => xs::mylength(ys,obj,pos-1)
I am trying to write a function that returns the index of the passed value v in a given list x; -1 if not found. My attempt at the solution:
let rec index (x, v) =
let i = 0 in
match x with
[] -> -1
| (curr::rest) -> if(curr == v) then
i
else
succ i; (* i++ *)
index(rest, v)
;;
This is obviously wrong to me (it will return -1 every time) because it redefines i at each pass. I have some obscure ways of doing it with separate functions in my head, none which I can write down at the moment. I know this is a common pattern in all programming, so my question is, what's the best way to do this in OCaml?
Mutation is not a common way to solve problems in OCaml. For this task, you should use recursion and accumulate results by changing the index i on certain conditions:
let index(x, v) =
let rec loop x i =
match x with
| [] -> -1
| h::t when h = v -> i
| _::t -> loop t (i+1)
in loop x 0
Another thing is that using -1 as an exceptional case is not a good idea. You may forget this assumption somewhere and treat it as other indices. In OCaml, it's better to treat this exception using option type so the compiler forces you to take care of None every time:
let index(x, v) =
let rec loop x i =
match x with
| [] -> None
| h::t when h = v -> Some i
| _::t -> loop t (i+1)
in loop x 0
This is pretty clearly a homework problem, so I'll just make two comments.
First, values like i are immutable in OCaml. Their values don't change. So succ i doesn't do what your comment says. It doesn't change the value of i. It just returns a value that's one bigger than i. It's equivalent to i + 1, not to i++.
Second the essence of recursion is to imagine how you would solve the problem if you already had a function that solves the problem! The only trick is that you're only allowed to pass this other function a smaller version of the problem. In your case, a smaller version of the problem is one where the list is shorter.
You can't mutate variables in OCaml (well, there is a way but you really shouldn't for simple things like this)
A basic trick you can do is create a helper function that receives extra arguments corresponding to the variables you want to "mutate". Note how I added an extra parameter for the i and also "mutate" the current list head in a similar way.
let rec index_helper (x, vs, i) =
match vs with
[] -> -1
| (curr::rest) ->
if(curr == x) then
i
else
index_helper (x, rest, i+1)
;;
let index (x, vs) = index_helper (x, vs, 0) ;;
This kind of tail-recursive transformation is a way to translate loops to functional programming but to be honest it is kind of low level (you have full power but the manual recursion looks like programming with gotos...).
For some particular patterns what you can instead try to do is take advantage of reusable higher order functions, such as map or folds.