Related
I need to concatenate two lists in Dart and saw that there are at least two different methods to do so. One is list1.addAll(list2) and the other is list1.followedBy(list2).
I wonder what's the difference? The documentation refers to the latter as "lazy concatenation". Does it mean that under the hood the elements are copied in the first case, but only referenced in the latter? Or is there something more?
Lazy loading (in this case lazy concatenation) means that some resources are not evaluated before they are necessary. By contrast, eager loading (or eager concatenation) means that the resource is fully evaluated.
So, lazy concatenation means that the concatenation is known to be executed, but its final evaluation is postponed until it is needed. Also, eager concatenation means that the whole concatenation process is fully done.
list1.addAll(list2) grows and mutates list1 to include the elements of list2. If list2 has m elements, then memory consumption from list1.addAll(list2) will by grow O(m).
More visually, if you have:
list1 list2
+---+---+---+---+ +---+---+
| o | o | o | o | | o | o |
+-|-+-|-+-|-+-|-+ +-|-+-|-+
| | | | | |
v v v v v v
A B C D E F
then list1.addAll(list2) will produce:
list1 list2
+---+---+---+---+---+---+ +---+---+
| o | o | o | o | o | o | | o | o |
+-|-+-|-+-|-+-|-+-|-+-|-+ +-|-+-|-+
| | | | | | | |
v v v v \ \______|__ |
A B C D \ ______/ \|
\ / |
| v
v F
E
Note that mutating list2 afterward will not affect the contents of list1.
list1.followedBy(list2) returns an Iterable (not a List). When you iterate over the that Iterable, you will iterate over list1 and then iterate over list2. list1.followedBy(list2) does not not mutate list1 and should not allocate a new List. Memory consumption from list1.followedBy(list2) will grow by O(1) since no Lists are grown nor created.
In this case, mutating list2 afterward will affect the Iterable returned by followedBy:
void main() {
var list1 = [1, 2, 3];
var list2 = [4, 5, 6];
var list1Copy = [...list1];
list1Copy.addAll(list2);
print(list1Copy); // Prints: [1, 2, 3, 4, 5, 6]
var concatenated = list1.followedBy(list2);
print(concatenated.toList()); // Prints: [1, 2, 3, 4, 5, 6]
list2.add(7);
print(list1Copy); // Prints: [1, 2, 3, 4, 5, 6]
print(concatenated.toList()); // Prints: [1, 2, 3, 4, 5, 6, 7]
}
I am studying for an exam and I am looking at an example of nested list comprehensions from the book "Learn you a Haskell", and I was hoping if anyone could explain me step by step how to analyze it and come out with its output.
let xxs = [[1,2,3],[2,3,4],[4,5]]
[ [ x | x <- xs, even x] | xs <- xxs ]]
Output: ([[2],[2,4],[4]])
[ [ x | x <- xs, even x] | xs <- xxs ]
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
[ [ x | x <- [1,2,3], even x] , [ x | x <- [2,3,4], even x] , [ x | x <- [4,5], even x] ]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Or
[ [ x | x <- xs, even x] | xs <- xxs ]
map (\xs -> [ x | x <- xs, even x] ) xxs
map (\xs -> filter even xs) [[1,2,3],[2,3,4],[4,5]]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Note this isn't the transformation that GHC actually does, just a way of writing it that might help you understand the output.
List comprehensions could have been defined by few identities:
[ f x | x <- [], ... ] === []
[ f x | x <- [y], ... ] === [ f y | {y/x}... ] -- well, actually, it's
-- case y of x -> [ f y | {y/x}... ] ; _ -> []
[ f x | x <- xs ++ ys, ...] === [ f x | x <- xs, ...] ++ [ f x | x <- ys, ...]
[ f x | True, ...] === [ f x | ... ]
[ f x | False, ...] === []
The handling of complex patterns (as opposed to simple variable patterns) is elided, only hinted at, for simplicity. {y/x}... means, y is substituted for x in .... For actual definition, see the Report.
It follows that
[ f x | xs <- xss, x <- xs] === concat [ [f x | x <- xs] | xs <- xss]
and
[ f x | x <- xs, test x ] === map f (filter test xs)
Your expression is equivalent to
[ [ x | x <- xs, even x] | xs <- xxs ] -- `]`, sic!
=
[ f xs | xs <- xxs ] where f xs = [ x | x <- xs, even x]
Which is to say, there's nothing special about a list comprehension being used as a value expression in the definition of f. It looks "nested", but actually, it isn't.
What is nested, are the generator expressions separated by commas:
[ x | xs <- xss, x <- xs ] === concat [ [x | x <- xs] | xs <- xss ]
-- ^^^ nested generator
(the equivalency like we saw above.) So then,
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
=
[ [ x | x <- [1,2,3], even x]] ++ [[ x | x <- [2,3,4], even x]] ++ [[ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1], even x]++[ x | x <- [2], even x]++[ x | x <- [3], even x]
, [ x | x <- [2], even x]++[ x | x <- [3], even x]++[ x | x <- [4], even x]
, [ x | x <- [4], even x]++[ x | x <- [5], even x] ]
=
[ [ 1 | even 1]++[ 2 | even 2]++[ 3 | even 3]
, [ 2 | even 2]++[ 3 | even 3]++[ 4 | even 4]
, [ 4 | even 4]++[ 5 | even 5] ]
=
[ []++[ 2 ]++[], [ 2 ]++[]++[ 4 ], [ 4 ]++[] ]
=
[ [2], [2,4], [4] ]
Or, with filter if you'd prefer,
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ filter even [1,2,3], filter even [2,3,4], filter even [4,5] ]
=
[ [2], [2,4], [4] ]
I'm having trouble with an assignment from my Haskell class. I have already solved a partial problem of this task: I have to write a function that takes an Int and creates an infinite list with the multiples of that Int.
function :: Int -> [Int]
function d = [d*x | x <- [1..]]
Console:
ghci> take 10 (function 3)
gives
[3,6,9,12,15,18,21,24,27,30]
In the second task I have to extend the function so that it accepts a list of numbers and uses each value of that list as a factor (d previously). For example:
ghci> take 10 (function [3, 5])
should give
[3,5,6,9,10,12,15,18,20,21]
Already tried a list comprehension like
function d = [y*x | y <- [1..], x <- d]
but the function returns the list in an unsorted form:
[3,5,6,10,9,15,12,20,15,25]
We got the tip that we should use the modulo function of Haskell, but I have no real idea how to proceed exactly. Do you have a good tip for me?
If you think of d being a factor not as
y = x * d
but instead
y `mod` d == 0,
then you can source the list comprehension from the list [1..] and add a predicate function, for example:
function ds
| null ds = [1..]
| otherwise = [ x | x <- [1..], qualifies x ]
where
qualifies x = any (==0) $ (flip mod) <$> ds <*> [x]
A more expressive version which is perhaps easier to grasp in the beginning:
function' ds
| null ds = [1..]
| otherwise = [ x | x <- [1..], divByAnyIn ds x ]
where
divByAnyIn ds x =
case ds of
(d:ds') -> if x `mod` d == 0 then True
else divByAnyIn ds' x
_ -> False
I have a one liner.
import Data.List (nub)
f xs = nub [x|x<-[1..], d<-xs, x `mod` d == 0]
take 10 $ f [3,5] -- [3,5,6,9,10,12,15,18,20,21]
runtime should be O(n² + n*d) from the resulting list. The nub runs in O(n²). Would be nice to get rid of it.
g xs = [x |x<-[1..], let ys = map (mod x) xs in 0 `elem` ys]
This performs pretty ok. It should run in O (n*d). I also have this version which I thought performs at least as well as g, but apparently it performs better than f and worse than g.
h xs = [x |x<-[1..], or [x `mod` d == 0 |d<-xs] ]
I am not sure why that is, or is lazy as far as I can tell and I don`t see any reason why it should run slower. It especially does not scale as well when you increase the length of the input list.
i xs = foldr1 combine [[x, x+x ..] |x<- sort xs]
where
combine l [] = l
combine [] r = r
combine l#(x:xs) r#(y:ys)
| x < y = (x: combine xs r)
| x > y = (y: combine l ys)
| otherwise = (x: combine xs ys)
Not a one liner anymore, but the fastest I could come up with. I am not a hundred percent sure why it makes such a big difference on runtime if you right or left fold and if you sort the input list in advance. But it should not make a difference on the result since:
commutative a b = combine [a] [b] == combine [b] [a]
I find it completely insane to think about this Problem in terms of folding a recursive function over a list of endless lists of multiples of input coefficients.
On my System it is still about a factor of 10 slower than another solution presented here using Data.List.Ordered.
The answer here just shows the idea, it is not a optimized solution, there may exists many way to implement it.
Firstly, calculate all the value of each factors from the inputted list:
map (\d->[d*x|x<-[1..]]) xs
For example: xs = [3, 5] gives
[[3, 6, 9, ...], [5, 10, 15, ...]]
then, find the minimum value of 1st element of each list as:
findMinValueIndex::[(Int, [Int])]->Int
findMinValueIndex xss = minimum $
map fst $
filter (\p-> (head $ snd p) == minValue) xss
where minValue = minimum $ map (head . snd) xss
Once we found the list hold the minimum value, return it and remove the minimum value from list as:
sortMulti xss =
let idx = findMinValueIndex $ zip [0..] xss
in head (xss!!idx):sortMulti (updateList idx (tail $ xss!!idx) xss
So, for example, after find the first value (i.e. 3) of the result, the lists for find next value is:
[[6, 9, ...], [5, 10, 15, ...]]
repeat above steps we can construct the desired list. Finally, remove the duplicated values. Here is the completed coding:
import Data.Sequence (update, fromList)
import Data.Foldable (toList)
function :: [Int] -> [Int]
function xs = removeDup $ sortMulti $ map (\d->[d*x|x<-[1..]]) xs
where sortMulti xss =
let idx = findMinValueIndex $ zip [0..] xss
in head (xss!!idx):sortMulti (updateList idx (tail $ xss!!idx) xss)
removeDup::[Int]->[Int]
removeDup [] = []
removeDup [a] = [a]
removeDup (x:xs) | x == head xs = removeDup xs
| otherwise = x:removeDup xs
findMinValueIndex::[(Int, [Int])]->Int
findMinValueIndex xss = minimum $
map fst $
filter (\p-> (head $ snd p) == minValue) xss
where minValue = minimum $ map (head . snd) xss
updateList::Int->[Int]->[[Int]]->[[Int]]
updateList n xs xss = toList $ update n xs $ fromList xss
There is a pretty nice recursive solution
function' :: Int -> [Int]
function' d = [d * x | x <- [1..]]
braid :: [Int] -> [Int] -> [Int]
braid [] bs = bs
braid as [] = as
braid aa#(a:as) bb#(b:bs)
| a < b = a:braid as bb
| a == b = a:braid as bs # avoid duplicates
| otherwise = b:braid aa bs
function :: [Int] -> [Int]
function ds = foldr braid [] (map function' ds)
braid function builds the desired list "on the fly" using only input's head and laziness
If you want to do it with the modulo function, you can define a simple one-liner
foo ds = filter (\x -> any (== 0) [mod x d | d <- ds]) [1..]
or, in the more readable form,
foo ds = filter p [1..]
where
p x = any id [ mod x d == 0 | d <- ds]
= any (== 0) [ mod x d | d <- ds]
= not $ null [ () | d <- ds, mod x d == 0]
= null [ () | d <- ds, mod x d /= 0]
= null [ () | d <- ds, rem x d > 0]
With this, we get
> take 20 $ foo [3,5]
[3,5,6,9,10,12,15,18,20,21,24,25,27,30,33,35,36,39,40,42]
But, it is inefficient: last $ take 20 $ foo [300,500] == 4200, so to produce those 20 numbers this code tests 4200. And it gets worse the bigger the numbers are.
We should produce n numbers in time roughly proportional to n, instead.
For this, first write each number's multiples in their own list:
[ [d*x | x <- [1..]] | d <- ds ] ==
[ [d, d+d ..] | d <- ds ]
Then, merge these ordered increasing lists of numbers in an ordered fashion to produce one ordered non-decreasing list of numbers. The package data-ordlist has many functions to deal with this kind of lists:
import qualified Data.List.Ordered as O
import Data.List (sort)
bar :: (Ord a, Num a, Enum a) => [a] -> [a]
bar ds = foldr O.merge [] [ [d, d+d ..] | d <- ds ]
= O.foldt' O.merge [] [ [d, d+d ..] | d <- ds ] -- more efficient,
= O.mergeAll [ [d, d+d ..] | d <- sort ds ] -- tree-shaped folding
If we want the produced list to not contain any duplicates, i.e. create an increasing list, we can change it to
baz ds = O.nub $ foldr O.merge [] [ [d, d+d ..] | d <- ds ]
= foldr O.union [] [ [d, d+d ..] | d <- ds ]
= O.foldt' O.union [] [ [d, d+d ..] | d <- ds ]
= O.unionAll [ [d, d+d ..] | d <- sort ds ]
= (O.unionAll . map (iterate =<< (+)) . sort) ds
Oh, and, unlike the quadratic Data.List.nub, Data.List.Ordered.nub is linear, spends O(1) time on each element of the input list.
Construct a predicate called fPairsAtoms/3 so that given an atom (first argument), and a list of pairs, unify a third parameter with the filtered list of pairs by selecting only the pairs that have the first component as the atom of the first argument.
Example:
fPairsAtoms(sA,[[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]],X)
Result:
X = [[sA,abbsB],[sA,bb]]
I do not understand ..... What should I face these types of exercises?
Can you help me find a solution?
Today I started with prolog, I am a newbie in every way.
If you've just started today, it probably is a bit too soon for you to tackle this problem.
First you should understand what Prolog terms are: atoms, logical Variables, compound terms foo(x,X,bar(baz)).
Then you should understand unification, a = a, a = A, A = a, A = foo(a), foo(A) = foo(a), [atom, B] = [A, bar].
You should understand lists representation, where
[ A, B, C ]
= [A, B | [C] ]
= [A | [B , C ]]
= [A | [B | [C] ]]
= ....
= [A , B , C | []]
so that unifying [A | B] = [a] succeeds, resulting in also unifying A = a and B = [], but unifying [A | B] = [] fails.
Then you need to understand predicates, which under procedural interpretation mean,
to_prove(This) :- need_to_prove(This) , and_also(That).
So that
fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]], X) :-
X = [ [sA,abbsB], [sA,bb]].
is a perfectly valid, though exceedingly narrow, definition of one.
But then so are also
fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [ [ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
X = [ [sA,abbsB] | [ [sA,bb]] ].
% and
fPairsAtoms(sA, [[bsA,sAsB],[sA,bb]] , Y) :-
Y = [ [sA,bb]].
% ... and
fPairsAtoms(sA, [] , Y) :-
Y = [].
and so also
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
Y = [ [sA,bb]],
X = [ [sA,abbsB] | Y ].
and thus
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
fPairsAtoms( L, Y),
Y = [ [sA,bb]],
X = [ [sA,abbsB] | Y ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
L = [[bsA,sAsB],[sA,bb]],
fPairsAtoms( L, Y),
X = [ [sA,abbsB] | Y ].
% and
fPairsAtoms(sA, [ [sA,abbsB] | L ], X) :-
fPairsAtoms( L, Y),
X = [ [sA,abbsB] | Y ].
% and so
fPairsAtoms(sA, [ A | L ], X) :-
A = [sA, B ],
fPairsAtoms( L, Y),
X = [ A | Y ].
% and even
fPairsAtoms(SA, [ A | L ], X) :-
A = [SA, B ],
fPairsAtoms( SA, L, Y),
X = [ A | Y ].
But on the other hand, in cases were there was no match, we saw that it is
fPairsAtoms(SA, [ A | L ], X) :-
A = [SB, B ],
dif( SA, SB),
fPairsAtoms( SA, L, Y),
X = Y .
% i.e.
fPairsAtoms(SA, [ [SB, B ] | L ], X) :-
dif( SA, SB),
fPairsAtoms( SA, L, X) .
So which one of the two clauses, that we've ended up with,
fPairsAtoms( SA, [ [SA, _] | L ], X) :-
fPairsAtoms( SA, L, Y),
X = [A | Y].
fPairsAtoms( SA, [ [SB, _] | L ], X) :-
dif( SA, SB),
fPairsAtoms( SA, L, X).
is the right one? The answer is: both!
To filter the pairs in the list, you need to traverse it while comparing the given atom with the first element of each pair. A trivial predicate to traverse a list would be:
traverse([]).
traverse([Head| Tail]) :-
traverse(Tail).
The predicate in your problem description is terribly named and don't follow recommended Prolog coding guidelines. Let's rename it to filter_pairs_by_key/3 and change the argument order to filter_pairs_by_key(Pairs, SearchKey, FilteredPairs). Also, the recommended representation for a pair in Prolog is Key-Value. There are standard predicates and library predicates that expect this representation (e.g. keysort/2). Based on the traverse/2 predicate template and the code style recommendations, we can write:
filter_pairs_by_key([], _, []).
filter_pairs_by_key([Key-Value| Pairs], SearchKey, [Key-Value| FilteredPairs]) :-
Key = SearchKey,
filter_pairs_by_key(Pairs, Atom, FilteredPairs).
filter_pairs_by_key([Key-_| Pairs], SearchKey, FilteredPairs) :-
Key \= SearchKey,
filter_pairs_by_key(Pairs, SearchKey, FilteredPairs).
Note that I'm using two clauses for the non-empty list case: one when the pair key matches the atom and one when the match fails.
Sample call:
| ?- filter_pairs_by_key([basA-absAb,ab-bbsA,sA-abbsB,bsA-sAsB,sA-bb], sA, FilteredPairs).
FilteredPairs = [sA-abbsB,sA-bb] ?
yes
More can be said about this problem and this particular solution but, as mentioned in the comments, this is not a beginners exercise. Consider the comments recommendations and after being comfortable with Prolog list notation play with this solution.
I want to create a list of Fibonacci numbers.
I want to call fib x and it should give me a list till the xth element.
How do I achieve that.
I would calculate fib numbers like this:
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
How do I put the result in a list to call the list till the element I need?
A compact definition (that scales linear) is the following:
fib :: Num n => [n]
fib = 0 : nxt
where nxt = 1 : zipWith (+) fib nxt
fibN :: Num n => Int -> [n]
fibN = flip take fib
What we here do is constructing a list fib that is "cons" of 0 and nxt (the rest of the lists). nxt is defined in the where clause as a "cons" of 1 and and the result of zipWith (+) fib nxt. The zipWith elementwise adds the elements of fib and nxt together, since nxt is always one element "ahead" of fib, we thus add the two last elements together. We then take the first n elements in the fibN function.
So we obtain a list like:
fib nxt
| |
v v
+-------+ +-------+ +-------------+
| (:) | ,->| (:) | ,->| zipWith |
+---+---+ | +---+---+ | +-----+---+---+
| 0 | o---' | 1 | o---' | (+) | o | o |
+---+---+ +---+---+ +-----+-|-+-|-+
^ ^ | |
| `------------------|---'
`-------------------------------'
In case we thus evaluate up to the third element, this means that we call zipWith, and this will produce the sum of the head of fib and nxt and advance both points, like:
fib nxt
| |
v v
+-------+ +-------+ +-------+ +-------------+
| (:) | ,->| (:) | ,->| (:) | ,->| zipWith |
+---+---+ | +---+---+ | +---+---+ | +-----+---+---+
| 0 | o---' | 1 | o---' | 1 | o---' | (+) | o | o |
+---+---+ +---+---+ +---+---+ +-----+-|-+-|-+
^ ^ | |
| `------------------|---'
`-------------------------------'
and so on.
Not a fast way (because your function runs in exponential time), but using your function fib
nfibs :: Int -> [Integer]
nfibs n = take n (map fib [0..])