I am trying to reverse a list similar to (A,B,(C,(D,E)),F) to return something like (F,((E,D),C),B,A) in haskell.
I know how to return a single list:
rev :: [a] -> [a]
rev [] = []
rev (x:xs) = (rev xs) ++ [x]
but how would I go about this for nested lists?
A possible implementation is as follows:
data Tree a = Leaf a | Node [Tree a] deriving (Eq, Show)
rev (Leaf x) = Leaf x
rev (Node xs) = Node (go (reverse xs)) where
go ((Leaf y):ys) = Leaf y: go ys
go ((Node y):ys) = rev (Node y): go ys
go [] = []
A short test:
λ> tree = Node [Leaf 'A', Leaf 'B', Node [Leaf 'C', Node [Leaf 'D', Leaf 'E']]]
λ> rev tree
Node [Node [Node [Leaf 'E',Leaf 'D'],Leaf 'C'],Leaf 'B',Leaf 'A']
As Daniel Wagner pointed out, this can be implemented much simpler and more elegant:
rev2 (Leaf x) = Leaf x
rev2 (Node xs) = Node (reverse (map rev2 xs))
Related
fun reverse ( [] ) = ( [] )
| reverse (x::xs) = reverse (xs) :: [x]
why my this function of reversing a list is not working
Your function has type 'a list -> 'a list. :: has type 'a -> 'a list -> 'a list. Thus you can't pass the result of calling reverse as the first argument to ::.
You could use # as suggested by JRose because that has type 'a list -> 'a list -> 'a list and will concatenate the two lists but that is inefficient compared to ::. # is O(n). Using it makes reverse have O(n^2) runtime efficiency.
Instead, let's use a tail-recursive helper function to build up an accumulator list in reverse order using ::, then return that. Because :: is O(1), this has O(n) runtime efficiency which is much better.
fun reverse lst =
let
fun aux [] acc = acc
| aux (x::xs) acc = aux xs (x :: acc)
in
aux lst []
end
Consider reversing [1, 2, 3]:
reverse [1, 2, 3]
aux [1, 2, 3] []
aux [2, 3] [1]
aux [3] [2, 1]
aux [] [3, 2, 1]
[3, 2, 1]
Further reading on the efficiency of # and ::. The link talks about OCaml, but the core principles are the same in SML.
I want to write a function that takes two lists as arguments and creates a list with a pair from each list consecutively, but in reverse.
for example:
reversezipLists [1, 2, 3] ['a', 'b', 'c']
would produce [('c', 3), ('b', 2), ('a', 1)].
Here is my attempt:
reversezipLists :: [a] -> [b] -> [(b,a)]
reversezipLists [] [] = []
reversezipLists [] ys = []
reversezipLists xs [] = []
reversezipLists (x:xs) (y:ys) = (y,x) : reversezipLists xs ys
the problem is the output of my code is: [('a',1),('b',2),('c',3)]. How can I reverse it?
Use an accumulator:
reversezipLists :: [a] -> [b] -> [(b, a)]
reversezipLists = go [] where
go acc [] _ = acc
go acc _ [] = acc
go acc (h1:t1) (h2:t2) = go ((h2, h1) : acc) t1 t2
Bonus points: the function is tail recursive. The basic idea is that we append new pairs to the acc during the left-to-right traverse through the lists. The stackish nature of Haskell lists makes the result reversed. Note that it will truncate longer list.
If you want to throw an error when the lists' lengths don't match, you can play a bit with patterns:
reversezipLists :: [a] -> [b] -> [(b, a)]
reversezipLists = go [] where
go acc [] [] = acc
go acc (h1:t1) (h2:t2) = go ((h2, h1) : acc) t1 t2
go _ _ _ = error "lists' sizes don't match"
r (x:xs) (y:ys) = (r xs ys) ++ [(y,x)]
r [] [] = []
r [1, 2, 3] ['a', 'b', 'c'] = [('c',3),('b',2),('a',1)]
it works only on lists of the same length
Can someone please explain how I can fix my program.
Very new to Haskell, been trying to create a length function that calculates the length of a list of any type.
I am aiming to do this using data as I want to create a brand new type to do so (this is the area of Haskell that I'm currently learning, which is why it might not be the most efficient implementation of this function)
data List a = Nil | Cons a (List a)
len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs
If I run it on len [1,2,3]
I get the error:
• Couldn't match expected type ‘List a0’
with actual type ‘[Integer]’
• In the first argument of ‘len’, namely ‘[1, 2, 3]’
In the expression: len [1, 2, 3]
In an equation for ‘it’: it = len [1, 2, 3]
The function definition is correct, but [1,2,3] is not a List a object, it is a [a] (or more canonical [] a). A list like [1,2,3] as List Int is:
len (Cons 1 (Cons 2 (Cons 3 Nil)))
Alternatively, you can make List a an instance of the IsList type class, and then use the -XOverloadedLists extension:
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts(IsList(Item, fromList, toList))
instance IsList (List a) where
type Item (List a) = a
fromList = foldr Cons Nil
toList Nil = []
toList (Cons x xs) = x : toList xs
Then we can use the OverloadedLists extension:
$ ghci -XOverloadedLists -XTypeFamilies
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/kommusoft/.ghci
Prelude> data List a = Nil | Cons a (List a)
Prelude> import GHC.Exts(IsList(Item, fromList, toList))
Prelude GHC.Exts> :{
Prelude GHC.Exts| instance IsList (List a) where
Prelude GHC.Exts| type Item (List a) = a
Prelude GHC.Exts| fromList = foldr Cons Nil
Prelude GHC.Exts| toList Nil = []
Prelude GHC.Exts| toList (Cons x xs) = x : toList xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> :{
Prelude GHC.Exts| len :: List a -> Int
Prelude GHC.Exts| len Nil = 0
Prelude GHC.Exts| len (Cons _ xs) = 1 + len xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> len [1,2,3]
3
I am learning Haskell at the moment and have come to a bit of a standstill. I'm trying to write a function that takes a predicate p and a list xs and returns the list of those elements of xs which immediately follow an element which passes the predicate p. Here is what I have :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter x (y:ys) =
if x y
then (map head [ys])
else
afterFilter x (tail ys)
test input : afterFilter (<0) [-4,7,-4,-8,3,-3,-6,0,-9,-1]
output : [7]
The trick is to pull two elements out of the input list by pattern-matching two cons cells. If the first element passes the predicate, we stick the second on the output. But don't forget to stick the second element back on the input list when you make the recursive call.
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter f [] = [] -- input list is empty
afterFilter f [x] = [] -- input list has only one element - no "next element" to return
afterFilter f (x:y:xs) =
let ys = afterFilter f (y:xs)
in (if f x then y:ys else rest)
However, a higher-level - and much more Haskellish - way to approach the problem would be to break it down into a pipeline of operations.
Pair up each item in the list with the element that follows it using zip, so we have a list of (element, next) pairs.
Use filter to drop the pairs for which element does not pass the predicate.
Use map to extract the next part of each surviving pair.
So the code looks like this:
pairWithSuccessors :: [a] -> [(a, a)]
pairWithSuccessors xs = zip xs (tail xs)
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p xs =
let withSuccessors = pairWithSuccessors xs (tail xs)
filtered = filter (\(element, next) -> p element) withSuccessors
filteredSuccessors = map (\(element, next) -> next) filtered
in filteredSuccessors
Or, written in point-free style:
afterFilter p = map snd . filter (p . fst) . pairWithSuccessors
Functions built with the composition operator . are read right-to-left: first pairWithSuccessors, then filter (p . fst), then map snd over the result.
GHC is good at working with lists: when compiled with optimisations, both approaches should produce roughly the same machine code - that is, there's no performance cost to the high-level solution
Following what you did, there are some strange things with your code :
The map head [ys] is very odd, and causes your function to stop : At the first element matching the predicate, your function returns a list containing its immediate successor and stops there. You still need to process the rest of the list.
Also, following your definition of the problem, each item which is a successor of an item passing the predicate should be on the resulting array. I may be wrong, but what I understood is that afterFilter (<0) [-1, -1, 1] should return [-1, 1].
However, you're discarding one element you didn't check for by calling tail ys : You checked for y, but not for head ys.
Finally, by adding the edge cases, here is what you get :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter _ [] = []
afterFilter _ [_] = []
afterFilter x (y:ys#(z:zs)) =
if x y
then z : afterFilter x ys
else
afterFilter x ys
Try:
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p [] = []
afterFilter p [_] = []
afterFilter p (x1:x2:xs)
| p x1 = x2:rest
| otherwise = rest
where rest = afterFilter p (x2:xs)
Or
afterFilter' :: (a -> Bool) -> [a] -> [a]
afterFilter' p xs = map snd $ filter (\(x, _) -> p x) $ zip xs (tail xs)
Or
afterFilter'' :: (a -> Bool) -> [a] -> [a]
afterFilter'' p xs = [y | (x, y) <- zip xs (tail xs), p x]
What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]