Very new to Haskell, and trying to create my own reverse function. Wrote this here, but it always returns an empty list [] :
reverse' :: [a] -> [a]
reverse' xs = [xs !! k | k <- [((length xs) - 1)..0]]
Can anyone explain what I'm doing wrong?
Thanks
Wherever you have your code to form the list of tuples, encapsulate that code in a reverse function using brackets (reverse(code)) or reverse $ <code> and the result will be the reverse.
The "take" function takes an integer and your list and produces the first "n" elements, while "drop" will give you the remainder of the list besides these elements: take :: Int -> [a] -> [a] drop :: Int -> [a] -> [a] Getting the 5 smallest numbers in a list is easy when you combine take and sort .
The principle of tail recursion is to perform all computation first before the recursive call, often giving the results of the computation as additional argument to the recursively called function. Thus in tail recursion the recursive call is the last logic instruction in the recursive function.
Elem Function This function is used to check whether the supplied list contains a specific element or not. Accordingly, it either returns a true or a false. The following code checks whether the supplied list of elements contains the value 786.
As groovy mentioned, Haskell ranges are mostly incremental - that is, it has no idea how to construct a decreasing list unless you give it some hint. Have a look at a ghci session below:
Prelude> [5..0]
[]
Prelude> [5,4..0]
[5,4,3,2,1,0]
So, you can construct something like this:
foo xs = [(length xs-1), (length xs -2)..0]
rev xs = [xs !! k| k <- foo xs]
which checks out in ghci like this:
Prelude> rev [1..5]
[5,4,3,2,1]
Have a look at Unexpected result while reversing a list and How can I write reverse by foldr efficiently in Haskell? for other ideas on reversing a list.
oftentimes it helps to invent some invariant and write down some laws of preservation for it. Here notice that
reverse xs = reverse xs ++ []
reverse (x:xs) = (reverse xs ++ [x]) ++ []
= reverse xs ++ ([x] ++ [])
= reverse xs ++ (x:[])
reverse (x:(y:xs)) =
= reverse (y:xs) ++ (x:[])
= reverse xs ++ (y:x:[])
......
reverse (x:(y:...:(z:[])...)) =
= reverse [] ++ (z:...:y:x:[])
so if we define
reverse xs = rev xs [] where
rev (x:xs) acc = rev xs (x:acc)
rev [] acc = acc
we're set. :) I.e., for a call rev a b
, the concatenation of reversed a
and b
is preserved under a transformation of taking a head element from a
and prepending it to b
, until a
is empty and then it's just b
. This can even be expressed with the use of higher-order function until
following the English description, as
{-# LANGUAGE TupleSections #-}
reverse = snd . until (null.fst) (\(a,b)-> (tail a,head a:b)) . (, [])
We can also define now e.g. an revappend
function, using exactly the same internal function with a little tweak to how we call it:
revappend xs ys = rev xs ys where
rev (x:xs) acc = rev xs (x:acc)
rev [] acc = acc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With