Finding the index of a given element using tail recursion - haskell

I am trying to write a function to find the index of a given element using tail recursion. Lets say the list contains the numbers 1 through 10, and I am searching for 5, then the output should be 4. The problem I am having is 'counting' using tail recursion. However, I am not even sure if I need to maunally 'count' the number of recursive calls in this case. I tried using !! which does not help because it returns the element in a particular position. I need the the function to return the position of a particular element (the exact opposite).
I have been trying to figure this one out for a hours now.
Code:
whatIndex a [] = error "cannot search empty list"
whatIndex a (x:xs) = foo a as
where
foo m [] = error "empty list"
foo m (y:ys) = if m==y then --get index of y
else foo m ys
Note: I am trying to implement this without using library functions

Your helper function needs an additional parameter for the count.
whatIndex a as = foo as 0
where
foo [] _ = error "empty list"
foo (y:ys) c
| a == y = c
| otherwise = foo ys (c+1)
BTW, it's better form to give this function a Maybe return type instead of using errors. That's how elemIndex works too, for good reason. This would look like
whatIndex a as = foo as 0
where
foo [] _ = Nothing
foo (y:ys) c
| a == y = Just c
| otherwise = foo ys (c+1)

Note: I am trying to implement this without using library functions
This is not a good idea in general. A better exercise is this:
Figure out how to implement it using library functions.
Figure out how to implement whichever library functions you used in step 1 on your own.
This way you're learning three key skills:
What are the standard library functions, and examples of when they are useful.
How to break problems into smaller pieces
How to write basic functions like the ones in the libraries.
In this case, however, your whatIndex is more or less the same function as elemIndex in Data.List, so your problem reduces to writing your own version of this library function.
The trick here is that you want to increment a counter while you recurse down the list. There is a standard technique for writing tail recursive functions, which is called an accumulating parameter. It works like this:
You write an auxiliary function that, compared to the "front-end" function, takes an extra parameter (or more) to keep track of the extra information.
You then define the "real" function as a call to the auxiliary one.
So for elemIndex, the auxiliary function would be something like this (with i as the accumulating parameter for the current element index):
-- I'll leave the blanks for you to fill.
elemIndex' i x [] = ...
elemIndex' i x (x':xs) = ...
Then the "driver" function is this:
elemIndex x xs = elemIndex 0 x xs
But there is a serious problem here that I must mention: getting this function to perform well in Haskell is tricky. Tail recursion is a useful trick in strict (non-lazy) functional languages, but not so much in Haskell, because:
A tail-recursive function in Haskell can still blow the stack,
A non-tail-recursive function can run in constant space.
This older answer of mine shows an example of the second point.
So in your case, a non-tail-recursive solution is probably the easiest one you can give that will run in constant space (i.e., not blow the stack on a long list):
elemIndex x xs = elemIndex' x (zip xs [0..])
elemIndex' x pairs = snd (find (\(x', i) -> x == x') pairs)
-- | Combine two lists by pairing together their first elements, their second
-- elements, etc., until one of the lists runs out.
--
-- EXERCISE: write this function on your own!
zip :: [a] -> [b] -> [(a, b)]
zip xs ys = ...
-- | Return the first element x of xs such that pred x == True. Returns Nothing if
-- there isn't one, Just x if there is one.
--
-- EXERCISE: write this function on your own!
find :: (a -> Bool) -> [a] -> Maybe a
find pred xs = ...

Related

Haskell: Parse error in pattern x ++ xs

Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:
myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
if length (x ++ xs) == i && length xs == 1 then xs!!0
else myElementAt x i
Which gives me Parse error in pattern: x ++ xs. The questions:
Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.
Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.
Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.
In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.
Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:
[] ++[0,1,2,3]
[0] ++ [1,2,3]
[0,1] ++ [2,3]
[0,1,2] ++ [3]
[0,1,2,3]++ []
Which one should the runtime choose?
Presumably, you're trying to match the head and tail part of a list. Let's step through it:
myElementAt (x:_) 0 = x
This means that if the head is x, the tail is something, and the index is 0, return the head. Note that your x ++ x is a concatenation of two lists, not the head and tail parts.
Then you can have
myElementAt(_:tl) i = myElementAt tl (i - 1)
which means that if the previous pattern was not matched, ignore the head, and take the i - 1 element of the tail.
In patterns, you can only use constructors like : and []. The append operator (++) is a non-constructor function.
So, try something like:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = ...
There are more issues in your code, but at least this fixes your first problem.
in standard Haskell pattern matches like this :
f :: Int -> Int
f (g n 1) = n
g :: Int -> Int -> Int
g a b = a+b
Are illegal because function calls aren't allowed in patterns, your case is just a special case as the operator ++ is just a function.
To pattern match on lists you can do it like this:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = // result
But in this case x is of type a not [a] , it is the head of the list and xs is its tail, you'll need to change your function implementation to accommodate this fact, also this function will fail with the empty list []. However that's the idiomatic haskell way to pattern match aginst lists.
I should mention that when I said "illegal" I meant in standard Haskell, there are GHC extensions that give something similar to that , it's called ViewPatterns But I don't think you need it especially that you're still learning.

The length of a list without the "length" function in Haskell

I want to see how long a list is, but without using the function length. I wrote this program and it does not work. Maybe you can tell me why? Thanks!
let y = 0
main = do
list (x:xs) = list (xs)
y++
list :: [Integer] -> Integer
list [] = y
Your program looks quite "imperative": you define a variable y, and then somehow write a do, that calls (?) the list function (?) that automagically seems to "return y" and then you want to increment y.
That's not how Haskell (and most functional and declarative) languages work:
in a declarative language, you define a variable only once, after the value is set, there is usually no way to alter its value,
in Haskell a do usually is used for monads, whereas the length is a pure function,
the let is a syntax construction to define a variable within the scope of an expression,
...
In order to program Haskell (or any functional language), you need to "think functional": think how you would solve the problem in a mathematical way using only functions.
In mathematics, you would say that the empty list [] clearly has length 0. Furthermore in case the list is not empty, there is a first element (the "head") and remaining elements (the "tail"). In that case the result is one plus the length of the tail. We can convert that in a mathematical expression, like:
Now we can easily translate that function into the following Haskell code:
ownLength :: [a] -> Int
ownLength [] = 0
ownLength (_:xs) = 1 + ownLength xs
Now in Haskell, one usually also uses accumulators in order to perform tail recursion: you pass a parameter through the recursive calls and each time you update the variable. When you reach the end of your recursion, you return - sometimes after some post-processing - the accumulator.
In this case the accumulator would be the so far seen length, so you could write:
ownLength :: [a] -> Int
ownLength = ownLength' 0
where ownLength' a [] = a
ownLength' a (_:xs) = ownLength' (a+1) xs
It looks you still think in an imperative way (not the functional way). For example:
you try to change the value of a "variable" (i.e. y++)
you try to use "global variable" (i.e. y) in the body of the list function
Here is the possible solution to your problem:
main = print $ my_length [1..10]
my_length :: [Integer] -> Integer
my_length [] = 0
my_length (_:xs) = 1 + my_length xs
You can also run this code here: http://ideone.com/mjUwL9.
Please also note that there is no need to require that your list consists of Integer values. In fact, you can create much more "agnostic" version of your function by using the following declaration:
my_length :: [a] -> Integer
Implementation of this function doesn't rely on the type of items from the list, thus you can use it for a list of any type. In contrast, you couldn't be that much liberal for, for example, my_sum function (a potential function that calculates the sum of elements from the given list). In this situation, you should define that your list consists of some numerical type items.
At the end, I'd like to suggest you a fantastic book about Haskell programming: http://learnyouahaskell.com/chapters.
Other answers have already beautifully explained the proper functional approach. It looks like an overkill but here is another way of implementing the length function by using only available higher order functions.
my_length :: [a] -> Integer
my_length = foldr (flip $ const . (+1)) 0
I've found this solution in Learn you a haskell.
length' xs = sum [1 | _ <- xs]
It replaces every element of the list with 1 and sums it up.
Probably the simplest way is to convert all elements to 1 and then to sum the new elements:
sum . map (const 1)
For added speed:
foldl' (+) 0 . map (const 1)

Does Haskell allow a let expression for multiple pattern matchings?

Let's say I have a function which does some computation, with several patterns; implemented in the form of pattern matching.
Most of these patterns do (along with other things different from one to another) a treatment on a parameter, for which I use an intermediary variable in a let expression. But I find it really redundant to have the same let on many patterns, and I wonder if there is a way to define a let for several patterns?
Here is an example of my duplicated let :
data MyType a = Something a | Another Int [a]
myFunc (Something x) = -- return something, this isn't the point here
myFunc (Another 0 xs) =
let intermediary = some $ treatment xs
in doSthg intermediary 1
myFunc (Another 1 (x:xs)) =
let intermediary = some $ treatment xs
in doSthg1 intermediary 1 x
myFunc (Another 2 (x:x':xs)) =
let intermediary = some $ treatment xs
in doSthg2 intermediary 2 x x'
You can see that the parameter xs is always present when I use it for intermediary, and this could be factorised.
It could easily be achieved by using a helper function but I was wondering if what I am asking is possible without one. Please try to keep it simple for a beginner, and I hope my example is clear enough.
This particular problem can be worked around as follows:
myFunc2 (Something x) = returnSomething x
myFunc2 (Another n ys) =
let xs = drop n ys
x = head ys
x' = head (tail ys)
intermediate = some $ treatment xs
in case n of
0 -> doSomething intermediate n
1 -> doSomething1 intermediate n x
2 -> doSomething2 intermediate n x x'
Thanks to lazy evaluation x and x' will be only evaluated if their value is needed.
However - and this is a big however! - your code will give a runtime error when you try to call myFunc2 (Another 2 []) (and if doSomething2 actually uses x!) because to find out what x is, we need to evaluate head ys - and that'll crash for an empty list. The code you gave as an example also won't work (another runtime error) for Another 2 [] since there's no matching pattern, but there it's easier to supply a fall-back case.
This might not be a problem if you control the input and always make sure that the list in Another is long enough, but it's important to be aware of this issue!

“replace” a 3-tuple

I have the following list (it’s a length 2 list, but in my assignment I have a length +n list)
xxs = [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
I’m trying to “replace” one 3-tuple (p1 or p2 or p3 or p4 from the image bellow) by list index (n) and by sub-list index (p).
The function, at the end, should be like:
fooo newtuple n p = (…)
For example: (replace p3 for (98,98,98):
fooo (98,98,98) 2 1
[(11, 22, [(33,33,33) , (44,44,44)]) , (55, 66, [(98,98,98),(88,88,88)])]
I planned the code like following this steps:
Access the pn that I want to change. I manage to achieve it by:
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
“replace” the 3-tuple. I really need some help here. I’m stuck. the best code (in my head it makes some sense) that I’ve done: (remember: please don’t be too bad on my code, I’ve only been studying Haskell only for 5 weeks)
foo n p newtuple = fooAux newtuple fob
where fooAux _ [] = []
fooAux m ((_):ds) = m:ds
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
Finally I will put all back together, using splitAt.
Is my approach to the problem correct? I really would appreciate some help on step 2.
I'm a bit new to Haskell too, but lets see if we can't come up with a decent way of doing this.
So, fundamentally what we're trying to do is modify something in a list. Using functional programming I'd like to keep it a bit general, so lets make a function update.
update :: Int -> (a -> a) -> [a] -> [a]
update n f xs = pre ++ (f val) : post
where (pre, val:post) = splitAt n xs
That will now take an index, a function and a list and replace the nth element in the list with the result of the function being applied to it.
In our bigger problem, however, we need to update in a nested context. Luckily our update function takes a function as an argument, so we can call update within that one, too!
type Triple a = (a,a,a)
type Item = (Int, Int, [Triple Int])
fooo :: Triple Int -> Int -> Int -> [Item] -> [Item]
fooo new n p = update (n-1) upFn
where upFn (x,y,ps) = (x,y, update (p-1) objFn ps)
objFn _ = new
All fooo has to do is call update twice (once within the other call) and do a little "housekeeping" work (putting the result in the tuple correctly). The (n-1) and (p-1) were because you seem to be indexing starting at 1, whereas Haskell starts at 0.
Lets just see if that works with our test case:
*Main> fooo (98,98,98) 2 1 [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
[(11,22,[(33,33,33),(44,44,44)]),(55,66,[(98,98,98),(88,88,88)])]
First, we need a general function to map a certain element of a list, e.g.:
mapN :: (a -> a) -> Int -> [a] -> [a]
mapN f index list = zipWith replace list [1..] where
replace x i | i == index = f x
| otherwise = x
We can use this function twice, for the outer list and the inner lists. There is a little complication as the inner list is part of a tuple, so we need another helper function:
mapTuple3 :: (c -> c) -> (a,b,c) -> (a,b,c)
mapTuple3 f (x,y,z) = (x,y,f z)
Now we have everything we need to apply the replace function to our use case:
fooo :: Int -> Int -> (Int,Int,Int) -> [(Int,Int,[(Int,Int,Int)])]
fooo n p newTuple = mapN (mapTuple3 (mapN (const newTuple) p)) n xxs
Of course in the inner list, we don't need to consider the old value, so we can use const :: a -> (b -> a) to ignore that argument.
So you've tried using some ready-made function, (!!). It could access an item in a list for you, but forgot its place there, so couldn't update. You've got a solution offered, using another ready-made function split, that tears a list into two pieces, and (++) which glues them back into one.
But to get a real feel for it, what I suspect your assignment was aiming at in the first place (it's easy to forget a function name, and it's equally easy to write yourself a new one instead), you could try to write the first one, (!!), yourself. Then you'd see it's real easy to modify it so it's able to update the list too.
To write your function, best think of it as an equivalence equation:
myAt 1 (x:xs) = x
myAt n (x:xs) | n > 1 = ...
when n is zero, we just take away the head element. What do we do when it's not? We try to get nearer towards the zero. You can fill in the blanks.
So here we returned the element found. What if we wanted to replace it? Replace it with what? - this calls another parameter into existence,
myRepl 1 (x:xs) y = (y:xs)
myRepl n (x:xs) y | n > 1 = x : myRepl ...
Now you can complete the rest, I think.
Lastly, Haskell is a lazy language. That means it only calls into existence the elements of a list that are needed, eventually. What if you replace the 7-th element, but only first 3 are later asked for? The code using split will actually demand the 7 elements, so it can return the first 3 when later asked for them.
Now in your case you want to replace in a nested fashion, and the value to replace the old one with is dependent on the old value: newVal = let (a,b,ls)=oldVal in (a,b,myRepl p ls newtuple). So indeed you need to re-write using functions instead of values (so that where y was used before, const y would go):
myUpd 1 (x:xs) f = (f x:xs)
myUpd n ... = ...
and your whole call becomes myUpd n xxs (\(a,b,c)->(a,b,myUpd ... (const ...) )).

When destructuring tuples in Haskell, where can the elements be used?

I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.

Resources