Say, I got a list which length can be odd or even. Every iteration , I remove two items from the list. If there is one or no item at the end, I end the execution.
If I store (length list)/2 every loop, I will get e.g. [5,4,3...] for a list of length 10.
But what I want is [1,2,3,...] and I couldn't figure out a relationship between the list size and this sequence...
Is there a way to achieve this without having a variable storing the current count?
i.e. with func :: [Int] -> [Int] only
You can certainly do this without changing the type signature of func :: [Int] -> [Int]: have func call a different function, which takes an extra argument that is the counter you were talking about:
func :: [Int] -> [Int]
func = go 0
where go _ [] = []
go _ [x] = []
go n (a:b:xs) = n : a : b : go (succ n) xs
func [11,12..20]
[0,11,12,1,13,14,2,15,16,3,17,18,4,19,20]
If you are determined to do this without managing the counter variable yourself, you can do something more contorted, such as zipping your input list into 3-tuples (a,b,n), where a and b are pairs of items from your input list and n comes from [1,2..].
pairs :: [a] -> [(a,a)]
pairs [] = []
pairs [_] = []
pairs (a:b:xs) = (a,b) : pairs xs
func' :: [Int] -> [Int]
func' xs = concat $ zipWith (\n (a,b) -> [n,a,b]) [1,2..] $ pairs xs
func' [11,12..20]
[1,11,12,2,13,14,3,15,16,4,17,18,5,19,20]
This is quite a bit less readable in my opinion, and I would suggest you just do the easy, obvious thing in my first snippet.
Ok, here's another solution:
func :: [a] -> [Int]
func (_:_:as) = 1 : map (+1) (func as)
func _ = []
I'm a bit unclear what you want the base cases to be, so I guessed you wanted func [] = [] and func [_] = []. Correct me if I'm wrong, please.
Working through your 10 element list example:
func ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] =
1 : map (+1) (func ['c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']) =
1 : map (+1) (1 : map (+1) (func ['e', 'f', 'g', 'h', 'i', 'j'])) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (func ['g', 'h', 'i', 'j']))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (func ['i', 'j'])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (func []))))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) [])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : [])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : 2 : []))) =
1 : map (+1) (1 : map (+1) (1 : 2 : 3 : [])) =
1 : map (+1) (1 : 2 : 3 : 4 : [])) =
1 : 2 : 3 : 4 : 5 : []) =
[1,2,3,4,5]
Related
I don't understand how Haskell can destructure the array to a tuple
e.g., why this works
head :: [a] -> a
head (x:xs) = x
But this does not work
head :: [a] -> a
head [x:xs] = x
it's unintuitive to me
(x:xs) is not a tuple, (x, xs) is a pattern for a 2-tuple. (x:xs) is short for ((:) x xs) where (:) is (one of the two) data constructors for a list. The other one is [], the empty list.
The (:) data constructor has two fields: the first one (here x) is the head that points to the first item of the list, and the second one (here xs) points to the list of the remaining elements. So this looks like a linked list.
[x:xs] is a short variant of [(x:xs)], so it binds with a list of lists where the outer list contains a single element, and that single element matches with (x:xs) so a non-empty list with x the first item of the only sublist, and xs the remaining elements of that sublist.
why this works
head :: [a] -> a
head (x:xs) = x
But this does not work
head :: [a] -> a
head [x:xs] = x
This is a very common source of difficulty for people learning Haskell. These look similar in some cases, but mean different things:
The type [a] is equivalent to [] a, meaning “the type of lists of zero or more elements that all have type a”.
The pattern [p] is equivalent to p : [] and (:) p [], meaning “match a list of exactly one element that matches the pattern p”.
Note that a list pattern with a variable at the end matches any number of remaining elements, but if it ends with “nil” [] then it matches a fixed number of elements. Here are some examples for lists of length n:
xs — n ≥ 0 — more than zero elements; any list
p : xs — n ≥ 1 — more than one element; non-empty lists
p₁ : p₂ : xs — n ≥ 2 — more than two elements
p₁ : p₂ : p₃ : xs — n ≥ 3 — &c.
…
[] — n = 0 — exactly zero elements; empty lists
[p] — n = 1 — exactly one element; singleton lists
[p₁, p₂] — n = 2 — exactly two elements
[p₁, p₂, p₃] — n = 3 — &c.
…
Writing x : xs, which is the same as (:) x xs, matches a list of one or more elements. Putting that in parentheses (x : xs) is equivalent, it’s only necessary because of precedence rules: head x : xs means (head x) : xs, which is a valid expression but not a valid pattern.
Writing [x : xs], which is the same as (x : xs) : [] and (:) ((:) x xs) [], matches a list of exactly one element ([ e ]) where that element matches a list of one or more elements (e = x : xs). Here are some examples:
let { x : xs = [1] } in (x, xs) evaluates to (1, []) because:
x : xs matches 1 : []
x = 1
xs = []
And these are all equivalent:
[1]
1 : []
(:) 1 []
let { x : xs = [1, 2, 3] } in (x, xs) evaluates to (1, [2, 3]) because:
x : xs matches 1 : 2 : 3 : []
x = 1
xs = [2, 3]
And these are all equivalent:
[1, 2, 3]
1 : [2, 3]
1 : 2 : [3]
1 : 2 : 3 : []
(:) 1 ((:) 2 ((:) 3 []))
let { x : xs = "hi" } in (x, xs) evaluates to ('h', "i") because:
x : xs matches 'h' : 'i' : []
x = 'h'
xs = "i"
And these are all equivalent:
"hi"
'h' : "i"
'h' : 'i' : []
(:) 'h' ((:) 'i' [])
let { [x : xs] = [[1]] } in (x, xs) evaluates to (1, []) because:
[ x : xs ] matches [ [1] ]
x : xs matches 1 : []
x = 1
xs = []
let { [x : xs] = ["yo"] } in (x, xs) evaluates to ('y', "o") because:
[ x : xs ] matches [ ["yo"] ]
x : xs matches 'y' : 'o' : []
x = 'y'
xs = "o"
Neither x : xs nor [x : xs] matches an empty list []
[x : xs] does not match ["ya", "no"] because x : xs : [] does not match "ya" : "no" : [], because [] does not match "no" : []
[x : xs] does not match [[]] because x : xs does not match []
The following code represents a function which takes a list as an input and then combines subsequent repetitions of the same value into a sublist.
for example : pack ['a','a','b','b','b','a'] = [['a','a'], ['b','b','b'], ['a']]
pack :: [Char] -> [[Char]]
pack (x:xs) = ys : pack zs
where
(ys, zs) = takeall x (x:xs)
takeall _ [] = ([], [])
takeall x (y:ys)
| x == y = let (us, vs) = takeall x ys
in (y:us, vs)
| otherwise = ([], (y:ys))
I found this code in sample solution. I'm still a beginner at haskell but i've seen the similar problem once as an example for an algorithm in C language.while solving this problem it came to my mind to write the code with the help of higher order functions.I thought the combination of foldl,filter and concatMap could be a good solution for this problem, however i'm not quite sure about filter.I wanted to write a function for filter which goes through the list and compares each element with it's neighbour elements and if they are eqaul returns true. Writing a function like that could be easy but how should i combine it with other functions of higher order so the things that are true come to a list together?
How do you solve this problem with higher order functions?
Firstly, your takeall function can be replaced with the span function from Prelude:
pack :: [Char] -> [[Char]]
pack (x : xs) = ys : pack zs
where
(ys, zs) = span (== x) (x : xs)
pack [] = []
Then, you can get rid of the explicit recursion using unfoldr:
import Data.List (unfoldr)
pack2 :: [Char] -> [[Char]]
pack2 = unfoldr go
where
go (x : xs) = Just $ span (== x) (x : xs)
go [] = Nothing
main :: IO ()
main = do
print $ pack ['a', 'a', 'b', 'b', 'b', 'a']
print $ pack2 ['a', 'a', 'b', 'b', 'b', 'a']
Output:
["aa","bbb","a"]
["aa","bbb","a"]
I am overall confused, and looking for a very detailed and explanatory answer, of how this code works:
let xs = [1] ++ concatMap (\x -> [x+1,x*10]) xs in xs
How does concatMap know what to map and concat over?
I understand more basic examples:
let x = [1] ++ x
Here it gets evaluated like [1] ++ [1] ++ [1] ..
But I don't seem to understand the first example with concatMap. It just doesn't make sense to me. I can work with recursion frequently without problems. However, that one piece of code is very confusing.
Let's try a much simpler example:
let xs = 1 : xs in xs
OK, so xs points to a (:) node. The head-pointer from here points to 1, and the tail-pointer points to xs (i.e., back to itself). So this is either a circular list, or an infinite list. (Haskell regards the two as the same thing.) So far, so good.
Now, let's try a harder example:
let xs = 1 : map (+1) xs in xs
Do you know what this will do?
So xs points to a (:) node. The head-pointer points to 1. The tail-pointer points to the expression map (+1) xs, with xs pointing back to the top again.
If you try to "look at" the contents of this list, it will cause the map expression to start executing. The definition of map is
map f js =
case js of
k:ks -> (f k) : (map f ks)
[] -> []
So map looks at xs to see if it's [] or (:). As we know, it's (:). So the first pattern applies.
What this means is that the entire map (+1) xs expression gets overwritten with (:), with its head-pointer pointing to (+1) 1 and its tail-pointer pointing to map (+1) xs2 (with xs2 denoting a pointer to the tail of xs).
At this point, inspecting (+1) 1 turns it into 2. So now we basically have
xs = 1 : 2 : map (+1) xs2
^ |
|___________|
This cycle repeats as you examine the list. Critically, at every moment map is pointing to a node just before itself. If it ever caught up to itself, you would have a problem. But map only ever looks at nodes we've already calculated, so it's fine.
The net result, then, is xs = 1 : 2 : 3 : 4 : ...
If you can understand that, you ought to be able to understand your own more complicated example.
If you want to make your head hurt, try:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
This is a standard Haskell incantation for spitting out the Fibonacci numbers in O(N) time (rather than O(N*N) as the more obvious recursion would give you).
Think of concatMap as a simple composition of concat and map (concat . map).
In this particular case, you are initializing xs with 1. Once you start running your map, it will lift the lambda to operate on 1 (the first position in the list) and create a list containing two values, 2 and 10. Concat just extracts those two values from that list and puts them naked in xs, concatenating them with the existing 1. At this point, xs contains 1, 2 and 10 (xs = [1,2,10]).
Now, xs contains 1, 2 and 10 and map will repeat the process (of course, starting from the second position in the list), now operating on 2 and creating a list containing 3 and 20 and a second list containing 11 and 100 when operating on 10 (third position in the list). Concat will now extract those 4 values and append them to the contents of xs. Now xs contains 1, 2, 10, 3, 20, 11 and 100 (xs = [1,2,10,3,20,11,100]).
And you can rinse and repeat, this time map operating on the fourth position in the list (and every subsequent position), and concat doing its work to remove the new list containers and place the values directly into the top level list. As you can see, this process will generate that infinite list.
Does this help?
First, what is concat? It concatenates lists, presented to it in a list:
concat [ [1], [2], [3] ] = [ 1, 2, 3 ]
concat [ [1], [2,22], [3] ] = [ 1, 2, 22, 3 ]
and so forth. What does map do? It transforms each element in a list it is presented with:
map (1+) [1, 2, 3] = [ 2, 3, 4 ]
map (:[]) [1, 2, 3] = [ [1], [2], [3] ]
map (\x-> [x+1, x*10]) [1, 2, 3] = [ [2,10], [3,20], [4,30] ]
But concatMap f xs is the same as concat (map f xs):
concatMap (\x-> [x+1, x*10]) [1, 2, 3]
= concat (map (\x-> [x+1, x*10]) [1, 2, 3])
= concat [ [2,10], [3,20], [4,30] ]
= [ 2,10, 3,20, 4,30 ]
But, it doesn't need to see the input list through to its end, in order to proceed, producing its elements one by one. This is because of Haskell's laziness. Simply,
concat [ [2,10], [3,20], [4,30] ]
= [ 2,10, 3,20, 4,30 ]
= [ 2,10] ++ concat [ [3,20], [4,30] ]
This means that actually,
concat xs == foldr (++) [] xs
-- concat [a,b,...,n] = a ++ (b ++ (... ++ (n++[])...))
and
concatMap f xs == foldr ((++).f) [] xs
-- concatMap f [a,b,...,n] = f a ++ (f b ++ (... ++ (f n++[])...))
so it does work incrementally. For your example,
let xs = [1] ++ concatMap (\x -> [x+1,x*10]) xs in xs
== let xs = [1] ++ foldr ((++).(\x -> [x+1,x*10])) [] xs in xs
== let xs = [1] ++ foldr (\x -> ([x+1,x*10] ++)) [] xs in xs
== let xs = [1] ++ foldr (\x r -> x+1 : x*10 : r) [] xs in xs
Which simply means: xs is a list, which contains 1, and then x+1 and x*10 for each element x in xs - from the start again. We could write this down also as
xs = 1 : [y | x <- xs, y <- [x+1, x*10]]
So for 1, 2 and 10 will be "appended" at list's end, then for 2, 3 and 20 will be produced, for 10 - 11 and 100, and so on:
xs = 1 a b c d e f g h ....
[2,10]=[a,b]
= 1 2 10 c d e f g h ....
[3,20]=[c,d]
= 1 2 10 3 20 e f g h ....
[11,100]=[e,f]
....
Of course this won't be evaluated on its own; the definition is "dormant" until used, e.g. to print the first 6 elements of xs:
Prelude> let xs = 1 : [y | x <- xs, y <- [x+1, x*10]]
Prelude> take 6 xs
[1,2,10,3,20,11]
As we can see, what's really been defined here is not an infinite list - there are no infinite things after all - but a process of calculating as much of its elements as might be needed.
Yet another way of writing this definition is
xs = 1 : next xs
where
next (x:xs) = x+1 : x*10 : next xs
where the computation's structure is seen yet clearer: next "looks back" into xs as it is being defined, first 1 notch back; then 2; then 3; etc. (because it produces two new list elements for each one it consumes; this definition is thus productive). This is characteristic of a "corecursive" definition. Its calculation proceeds as
take 6 xs
= take 6 xs where xs=1:next xs -- next looks 1 element back
= 1:take 5 xs1 where xs=1:xs1; xs1=next xs
= 1:take 5 xs1 where xs1=2:10:next xs1 -- 2 elements back
= 1:2:take 4 xs2 where xs1=2:xs2; xs2=10:next xs1
= 1:2:10:take 3 xs3 where xs1=2:xs2; xs2=10:xs3; xs3=next xs1
= 1:2:10:take 3 xs3 where xs2=10:xs3; xs3=3:20:next xs2 -- 3 elements
= 1:2:10:3:take 2 xs4 where xs2=10:xs3; xs3=3:xs4; xs4=20:next xs2
= 1:2:10:3:20:take 1 xs5 where xs2=10:xs3; xs3=3:xs4; xs4=20:xs5; xs5=next xs2
= 1:2:10:3:20:take 1 xs5 where xs3=3:xs4; xs4=20:xs5; xs5=11:100:next xs3 -- 4
....
I have function change which replace some characters to numbers. Here it is:
change [] = []
change (x:xs) | x == 'A' = '9':'9':change xs
| x == 'B' = '9':'8':change xs
| otherwise = change xs
and the output is:
Main> change "aAB11s"
"9998"
but I need this:
Main> change "aAB11s"
"a999811s"
How can I do this?
Try this:
change [] = []
change (x:xs) | x == 'A' = '9':'9':change xs
| x == 'B' = '9':'8':change xs
| otherwise = x:change xs
The only change is in otherwise.
In addition to #kostya 's answer, you don't need to write the recursive part youself, try this out:
change :: String -> String
change xs = concatMap chToStr xs
where chToStr 'A' = "99"
chToStr 'B' = "98"
chToStr x = [x]
or, more point-freely (actually this is preferred if the point-free refactoring doesn't hurt the readability):
change :: String -> String
change = concatMap chToStr
where chToStr 'A' = "99"
chToStr 'B' = "98"
chToStr x = [x]
And you can test the result:
λ> change "aAB11s"
"a999811s"
Some explanation:
It's tempting to do an elementwise replacement by passing map a function
f :: Char -> Char. But here you can't do that because for A, you want two characters, i.e. 99, so the function you want is of type Char -> String (String and [Char] in Haskell are equivalent) which does not fit the type signature.
So the solution is to also wrap other characters we don't care about into lists, and afterwards, we can perform a string concatenation(this function in Haskell is called concat) to get a string back.
Further, concatMap f xs is just a shorthand for concat (map f xs)
λ> map (\x -> [x,x]) [1..10]
[[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9],[10,10]]
λ> concat (map (\x -> [x,x]) [1..10])
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10]
λ> concatMap (\x -> [x,x]) [1..10]
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10]
Data.Lists.Split is actually not working winHugs interpreter. which can be get by splitEvery 3 ['a'..'z'] function
is it possible to achieve this without Data.Lists.Split ?
list of separate integers [5,5,5,6,6,6] -> to be [555,666] to concat every three numbers !
should be [Int]->[Int]
Yes, it's quite possible. You can proceed like this:
First write a function that takes three digits and "concat"s them into one number (this is quite easy using multiplication and addition).
Then you write another function which takes a list and processes its elements in threes using the previous function. Basically the definition of that function will look like the definition of map, except that you process three elements instead of one in the non-empty case (i.e. you use a pattern like x1:x2:x3:xs), and you call the previously defined function instead of one given as an argument.
Here's an implementation of splitEvery that should work for your purposes:
import Data.List
splitEvery _ [] = []
splitEvery n xs = chunk : splitEvery n remaining
where (chunk, remaining) = splitAt n xs
Let's make a general function that groups a given number of items, and applies a given function to each group.
groupMap :: ([a] -> b) -> Int -> [a] -> [b]
groupMap f n xs = go xs
where go [] = []
go xs = f (take n xs) : go (drop n xs)
OK, now what f should we pass in?
intListToInt :: [Int] -> Int
intListToInt xs = go xs 0
where go [] v = v
go (x:xs) v = go xs (x + v*10)
There are various different ways you could write this; I'm experimenting with the workhorse helper technique. Note that this type signature lines up nicely with the first argument of groupMap. Anyways...let's see if it works!
ghci> groupMap intListToInt 3 [5,5,5,6,6,6]
[555,666]
Yay! It even works for other stuff too. (some sketchy uses follow...)
ghci> groupMap (read :: String -> Int) 5 "1234554321"
[12345,54321]
ghci> groupMap (read :: String -> Bool) 4 "TrueTrueTrue"
[True,True,True]
ghci> groupMap sum 2 [1,2,3,4,5,6]
[3,7,11]
NB: If I'm not mistaken, intListToInt could benefit from a little more strictness:
{-# LANGUAGE BangPatterns #-}
intListToInt xs = go xs 0
where go [] !v = v
go (x:xs) !v = go xs (x + v*10)
Though I'm not at all familiar with which language pragmas Hugs supports.
Use show, concat and read:
map (read . (>>= show)) . splitEvery 3
Possible Solution:
Here is one possible solution, using only function from the Prelude:
group3 :: [Int] -> [Int]
group3 [] = []
group3 xs = toSingleNum (take 3 xs): (group3 (drop 3 xs))
where toSingleNum ys = read $ concat $ map show ys
There are, of course, innumerable ways to do this. This is one.
Explanation:
group3 works by using the take and drop functions and natural recursion to split the list into groups of 3, and applying toSingleNum to each of the groups.
Ignoring the application of take and drop, the function works roughly as below:
group3 [1,2,3,4,5,6,7,8,9]
toSingleNum [1,2,3] : group3 [4,5,6,7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : group3 [7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : group3 []
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : []
After toSingleNum is applied, we'd have:
123 : 456 : 789 : []
[123, 456, 789]
toSingleNum converts a list of numbers into a single number.
toSingleNum [1, 3, 4]
>>> 134
toSingleNum [12, 13, 14]
>>> 121314
The conversion in toSingleNum is done by converting the numbers to a String, then combining them, then converting back to a number.
toSingleNum [1, 3, 4]
read $ concat $ map show [1, 3, 4]
read $ concat $ ["1", "3", "4"]
read $ "134"
134
Further Reading:
If you're interested in Haskell, I'd recommend Graham Hutton's excellent "Programming in Haskell", or one of the tutorials listed on the Haskell Wiki.
First, split the list into chunks:
chunk n = unfoldr split
where
split [] = Nothing -- stop
split xs = Just $ splitAt n xs -- keep going
ghci> chunk 3 [1..6]
[[1,2,3],[4,5,6]]
The chunk function continues chopping n-sized chunks off the input list, until the list is empty. (unfoldr is one of the most under-appreciated functions in the standard library, by the way.)
Then turn each chunk into a number:
cumulate = foldl' (\x y -> x * 10 + y) 0
ghci> cumulate [4,5,6]
456
Now, compose these two functions together:
coalesce = map cumulate . chunk
ghci> coalesce [5,5,5,6,6,6]
[555,666]