How do you create a list-based matrix of 1's with given row and column counts? For example, like:
row=3,column=4 -> [[1,1,1,1],[1,1,1,1],[1,1,1,1]]
Here's an alternative method using list comprehension. Let's have a look at the basics:
Prelude> [ 2*x | x <- [1..4] ]
[2,4,6,8]
So that gives you one number for each element in the list [1..4]. Why not, instead of doubling x, just have a 1:
Prelude> [ 1 | x <- [1..4] ]
[1,1,1,1]
And if we want three of them, we can pull the same trick:
Prelude> [ [1|x<-[1..4]] | x<-[1..3] ]
[[1,1,1,1],[1,1,1,1],[1,1,1,1]]
Thus we can define
twoDlist r c = [ [1|x<-[1..c]] | x<-[1..r] ]
which gives
Prelude> twoDlist 3 4
[[1,1,1,1],[1,1,1,1],[1,1,1,1]]
You can do this with replicate:
onesMatrix rows cols = replicate rows (replicate cols 1)
import Control.Applicative
import Data.Functor
matrix r c = [1] <* [1..c] <$ [1..r]
Related
The point of this assignment is to understand list comprehensions.
Implementing Goldbach's conjecture for some natural number (otherwise the behavior does not matter) using several pre-defined functions and under the following restrictions:
no auxiliary functions
no use of where or let
only one defining equation on the left-hand side and the right-hand side must be a list comprehension
the order of the pairs in the resulting list is irrelevant
using functions from Prelude is allowed
-- This part is the "library"
dm :: Int -> [ Int ] -> [ Int ]
dm x xs = [ y | y <- xs , y `mod ` x /= 0]
da :: [ Int ] -> [ Int ]
da ( x : xs ) = x : da ( dm x xs )
primes :: [ Int ]
primes = da [2 ..]
-- Here is my code
goldbach :: Int -> [(Int,Int)]
-- This is my attempt 1
goldbach n = [(a, b) | n = a + b, a <- primes, b <- primes, a < n, b < n]
-- This is my attempt 2
goldbach n = [(a, b) | n = a + b, a <- takeWhile (<n) primes, b <- takeWhile (<n) primes]
Expected result: a list of all pairs summing up to the specified integer. But GHC complains that in the comprehension, n is not known. My gut tells me I need some Prelude function(s) to achieve what I need, but which one?
Update
parse error on input ‘=’
Perhaps you need a 'let' in a 'do' block?
e.g. 'let n = 5' instead of 'n = 5'
Disregarding the weird error you are talking about, I think that the problem you actually have is the following:
As mentioned by #chi and me, you can't use a and b in your final comprehension before you define a and b.
so you have to move it to the and.
Also: equality of integers is checked with (==) not (=) in haskell.
So you also need to change that.
This would be the complete code for your final approach:
goldbach n = [(a, b) | a <- takeWhile (<n) primes, b <- takeWhile (<n) primes, n == a + b]
A small test yields:
*Main> goldbach 5
[(2,3),(3,2)]
Update
If you want to achieve what you wrote in your comment, you can just add another condition to your comprehension
n `mod` 2 == 0
or even better: Define your funtion with a guard like this:
goldbach n
| n `mod` 2 == 0 = [(a, b) | a <- takeWhile (<n) primes, b <- takeWhile (<n) primes, n == a + b]
| otherwise = []
However, if I am not mistaken this has nothing to do with the actual Godbach conjecture.
This recent question got me thinking about Haskell's ability to work with infinite lists. There are plenty of other questions and answers about infinite lists on StackOverflow, and I understand why we can't have a general solution for all infinite lists, but why can't Haskell reason about some infinite lists?
Let's use the example from the first linked question:
list1 = [1..]
list2 = [x | x <- list1, x <= 4]
print list2
$ [1,2,3,4
#user2297560 writes in the comments:
Pretend you're GHCI. Your user gives you an infinite list and asks you to find all the values in that list that are less than or equal to 4. How would you go about doing it? (Keep in mind that you don't know that the list is in order.)
In this case, the user didn't give you an infinite list. GHC generated it! In fact, it generated it following it's own rules. The Haskell 2010 Standard states the following:
enumFrom :: a -> [a] -- [n..]
For the types Int and Integer, the enumeration functions have the following meaning:
The sequence enumFrom e1 is the list [e1,e1 + 1,e1 + 2,…].
In his answer to the other question, #chepner writes:
You know that the list is monotonically increasing, but Haskell does not.
The statements these users made don't seem to line up with the standard to me. Haskell created the list in an ordered fashion using a monotonic increase. Haskell should know that the list is both ordered and monotonic. So why can't it reason about this infinite list to turn [x | x <- list1, x <= 4] into takeWhile (<= 4) list1 automatically?
Theoretically, one could imagine a rewrite rule such as
{-# RULES
"filterEnumFrom" forall (n :: Int) (m :: Int).
filter (< n) (enumFrom m) = [m..(n-1)]
#-}
And that automatically would convert expressions such as filter (< 4) (enumFrom 1) to [1..3]. So it is possible. There is a glaring problem though: any variation from this exact syntactical pattern won't work. The result is that you end up defining a bunch of rules and you can longer ever be sure if they are triggering or not. If you can't rely on the rules, you eventually just don't use them. (Also, note I've specialized the rule to Ints - as was briefly posted as a comment, this may break down in subtle ways for other types.)
At the end of the day, to perform more advanced analysis, GHC would have to have some tracking information attached to lists to say how they were generated. That would either make lists less lightweight of an abstraction or mean that GHC would have some special machinery in it just for optimizing lists at compile time. Neither of these options is nice.
That said, you can always add your own tracking information by making a list type on top of lists.
data List a where
EnumFromTo :: Enum a => a -> Maybe a -> List a
Filter :: (a -> Bool) -> List a -> List a
Unstructured :: [a] -> List a
This may end up being easier to optimize.
So why can't it reason about this infinite list to turn [x | x <- list1, x <= 4] into takeWhile (<= 4) list1 automatically?
The answer isn't any more specific than "It doesn't use takeWhile because it doesn't use takeWhile". The spec says:
Translation: List comprehensions satisfy these identities, which may
be used as a translation into the kernel:
[ e | True ] = [ e ]
[ e | q ] = [ e | q, True ]
[ e | b, Q ] = if b then [ e | Q ] else []
[ e | p <- l, Q ] = let ok p = [ e | Q ]
ok _ = []
in concatMap ok l
[ e | let decls, Q ] = let decls in [ e | Q ]
That is, the meaning of a list comprehension is given by translation into a simpler language with if-expressions, let-bindings, and calls to concatMap. We can figure out the meaning of your example by translating it through the following steps:
[x | x <- [1..], x <= 4]
-- apply rule 4 --
let ok x = [ x | x <= 4 ]
ok _ = []
in concatMap ok [1..]
-- eliminate unreachable clause in ok --
let ok x = [ x | x <= 4 ]
in concatMap ok [1..]
-- apply rule 2 --
let ok x = [ x | x <= 4, True ]
in concatMap ok [1..]
-- apply rule 3 --
let ok x = if x <= 4 then [ x | True ] else []
in concatMap ok [1..]
-- apply rule 1 --
let ok x = if x <= 4 then [ x ] else []
in concatMap ok [1..]
-- inline ok --
concatMap (\x -> if x <= 4 then [ x ] else []) [1..]
I need to generate infinite sorted list of all coprimes.
The first element in each pair must be less than the second.
The sorting must be done in ascending order -- by the sum of pair's elements; and if two sums are equal, then by the pair's first element.
So, the resulting list must be
[(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)...`
Here's my solution.
coprimes :: [(Int, Int)]
coprimes = sortBy (\t1 t2 -> if uncurry (+) t1 <= uncurry (+) t2 then LT else GT) $ helper [2..]
where helper xs = [(x,y) | x <- xs, y <- xs, x < y, gcd x y == 1]
The problem is that I can't take n first pairs. I realize that sorting can't be done on infinite lists.
But how can I generate the same sequence in a lazy way?
While probably not the most optimal way it should works if you first generate all possible pairs and then filter them.
So using your criteria:
pairs :: [(Integer,Integer)]
pairs = [ (i,l-i) | l <- [1..], i <- [1..l-1] ]
coprimes :: [(Integer,Integer)]
coprimes = [ (i,j) | (i,j) <- pairs, 1 < i, i < j,gcd i j == 1]
produces
λ> take 10 coprimes
[(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)]
now of course you can put some of the stuff 1 < i and i < j comes to mind into the pairs definition or even join them but I think here it's more obvious what's going on
Here's a possible solution following Chapter 9 of Richard Bird's Thinking Functionally in Haskell:
coprimes = mergeAll $ map coprimes' [2..]
coprimes' n = [(n, m) | m <- [n+1..], gcd m n == 1]
merge (x:xs) (y:ys)
| s x < s y = x:merge xs (y:ys)
| s x == s y = x:y:merge xs ys
| otherwise = y:merge (x:xs) ys
where s (x, y) = x+y
xmerge (x:xs) ys = x:merge xs ys
mergeAll = foldr1 xmerge
And the result is:
> take 10 $ coprimes
[(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)]
Note that the natural definition of mergeAll would be foldr1 merge, but this doesn't work because it will try to find the minimum of the first elements of all the list before returning the first element, and hence you end up in an infinite loop. However, since we know that the lists are in ascending order and the minimum is the first element of the first list xmerge does the trick.
Note: this solution appears to be significantly (like 2 order of magnitudes) slower than Carsten "naive" answer. So I advise to avoid this if you are interested in performance. Yet it still is an interesting approach that might be effective in other situations.
As #Bakuriu suggests, merging an infinite list of infinite lists is a solution, but the devil is in the details.
The diagonal function from the universe-base package can do this, so you could write:
import Data.Universe.Helpers
coprimes = diagonal [ go n | n <- [2..] ]
where go n = [ (n,k) | k <- [n+1..], gcd n k == 1 ]
Note - this doesn't satisfy your sorted criteria, but I mention it because the functions in that package are useful to know about, and implementing a function like diagonal correctly is not easy.
If you want to write your own, consider decomposing the infinite grid N x N (where N is the natural numbers) into diagonals:
[ (1,1) ] ++ [ (1,2), (2,1) ] ++ [ (1,3), (2,2), (3,1) ] ++ ...
and filtering this list.
I need to generate infinite sorted list of all coprimes. The first element in each pair must be less than the second. The sorting must be done in ascending order -- by the sum of pair's elements; and if two sums are equal, then by the pair's first element.
So, we generate ascending pairs of sum and first element, and keep only the coprimes. Easy cheesy!
[ (first, second)
| sum <- [3..]
, first <- [2..sum `div` 2]
, let second = sum-first
, gcd first second == 1
]
I want to write a function that uses list comprehensions to generate a list of lists that works like this:
makeList 3 == [[1],[1,2],[1,2,3]]
makeList 5 == [[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5]]
makeList (-2) == []
I end up with this solution, but It not gives me what it needs from the question obviously:
let makelist x = [x | x <- x, y <- [1..x]]
So if I enter this
Prelude> makelist [3]
the output will shows like this:
[3,3,3]
I wanted to be a list in list first then I want it to be increased. Thank you for help!
Let's try generating an inner list first, for some limit m:
> let inner m = [1..m]
> inner 5
[1,2,3,4,5]
Now, observe that your outer list, for some limit n, is [inner 1, inner 2, inner 3, ..., inner n], or, in list comprehension form:
> let outer n = [inner m | m <- [1..n]]
> outer 3
[[1], [1,2], [1,2,3]]
so we can combine the two into the single list comprehension expression:
> let makeList n = [[1..m] | m <- [1..n]]
> makeList 4
[[1],[1,2],[1,2,3],[1,2,3,4]]
I propose you this:
make_list n = [ [1..m] | m <- [1..n] ]
However there's something strange in your first attempt:
make_list x = [x | x <- x, y <- [1..x]]
there you put x for every purpose. It just feels wrong.
A recursive version based in list generation as well,
makeList' :: Int -> [[Int]]
makeList' n
| n < 1 = []
| otherwise = [1..n] : makeList' (n-1)
makeList :: Int -> [[Int]]
makeList n = reverse $ makeList' n
makeList' returns the desired outcome in reverse order.
I just encountered this example on learnyouahaskell.com. However, I don't understand it at all.
ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [ [ x | x <- xs, even x ] | xs <- xxs]
[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]] -- This is the output
My problem is that while I do understand the idea of list comprehensions, I don't get what the xxs means.
If it was just the name of the list of lists, how can we split up a name and do something like xs <- xxs. To me that doesn't make sense at all.
Can someone help?
xxs is the list of lists bound in the let expression. I think you're being confused by the similarity of xxs and xs, they are just two independent names with no relation. You can replace xs with sublist or any other valid name.
ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [ [ x | x <- sublist, even x ] | sublist <- xxs]
So we're not splitting on the name we're just using the <- list comprehension operator to iterate over the elements of a [[a]] and then have another comprehension for iterating over the elements of each [a] sublist.