Smart looping over lists using | in Haskell - list

I am trying to build a logic sentence (such that only m propositions out of n propositions can be true) with a double loop, but get confused by the "|" token. I cannot find its precise meaning on Hoogle. The select gives a list of lists, a list of indexes that can be selected. With the indexes i want to build a conjunction of positive "selected" propositions and negative "non-selected" propositions. What am i doing wrong with the following code?
genXorM :: Int -> Int -> Form
genXorM n m = Disj [Conj [Neg $ PrpF $ P x, PrpF $ P y] | z <- select, y <- [0 .. n] \\ z, x <- z] where
select = combinations m [0 .. n]

genXorM :: Int -> Int -> Form
genXorM n m = Disj [Conj [Neg $ PrpF $ P x, PrpF $ P y] | z <- select, y <- [0 .. n] \\ z, x <- z] where
select = combinations m [0 .. n]
You have a “triple loop” here. It says:
For every combination z of m propositions:
For every proposition y not in z:
For every proposition x in z:
Produce the formula ¬x ∧ y
If I understand correctly that you want a conjunction of all the selected propositions x with the negation of all the non-selected ones y, that could be written with list comprehensions like this:
genXorM :: Int -> Int -> Form
genXorM n m = Disj
[ Conj
([PrpF (P p) | p <- x]
++ [Neg (PrpF (P n)) | n <- y])
| x <- select
, let y = [0 .. n] \\ x
]
where
select = combinations m [0 .. n]
Or without them, for example, using map and some helper functions to break down the problem into smaller pieces:
genXorM n m = Disj (map conjoin selected)
where
selected = combinations m [0 .. n]
conjoin z = Conj (map positive z ++ map negative (complement z))
positive = PrpF . P
negative = Neg . positive
complement x = [0 .. n] \\ x

Related

Count non-empty lists in a lists of lists

I am trying to count the number of non-empty lists in a list of lists with recursive code.
My goal is to write something simple like:
prod :: Num a => [a] -> a
prod [] = 1
prod (x:xs) = x * prod xs
I already have the deifniton and an idea for the edge condition:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [[]] = 0
I have no idea how to continue, any tips?
I think your base case, can be simplified. As a base-case, we can take the empty list [], not a singleton list with an empty list. For the recursive case, we can consider (x:xs). Here we will need to make a distinction between x being an empty list, and x being a non-empty list. We can do that with pattern matching, or with guards:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = -- …
That being said, you do not need recursion at all. You can first filter your list, to omit empty lists, and then call length on that list:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount = length . filter (…)
here you still need to fill in ….
Old fashion pattern matching should be:
import Data.List
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = if null x then 1 + (nonEmptyCount xs) else nonEmptyCount xs
The following was posted in a comment, now deleted:
countNE = sum<$>(1<$)<<<(>>=(1`take`))
This most certainly will look intimidating to the non-initiated, but actually, it is equivalent to
= sum <$> (1 <$) <<< (>>= (1 `take`))
= sum <$> (1 <$) . (take 1 =<<)
= sum . fmap (const 1) . concatMap (take 1)
= sum . map (const 1) . concat . map (take 1)
which is further equivalent to
countNE xs = sum . map (const 1) . concat $ map (take 1) xs
= sum . map (const 1) $ concat [take 1 x | x <- xs]
= sum . map (const 1) $ [ r | x <- xs, r <- take 1 x]
= sum $ [const 1 r | (y:t) <- xs, r <- take 1 (y:t)] -- sneakiness!
= sum [const 1 r | (y:_) <- xs, r <- [y]]
= sum [const 1 y | (y:_) <- xs]
= sum [ 1 | (_:_) <- xs] -- replace each
-- non-empty list
-- in
-- xs
-- with 1, and
-- sum all the 1s up!
= (length . (take 1 =<<)) xs
= (length . filter (not . null)) xs
which should be much clearer, even if in a bit sneaky way. It isn't recursive in itself, yes, but both sum and the list-comprehension would be implemented recursively by a given Haskell implementation.
This reimplements length as sum . (1 <$), and filter p xs as [x | x <- xs, p x], and uses the equivalence not (null xs) === (length xs) >= 1.
See? Haskell is fun. Even if it doesn't yet feel like it, but it will be. :)

How does haskell create a new list from another list?

Suppose we have a list
x = [1..10]
and we intend to create another list y using this in this manner :
y= [a|a<-x]
So while creating the list y from x, it accesses each element of x( from 1 to 10) and inserts it in y in the same order. As a list in haskell is singly linked list, we can insert a new element only at its head. So first it inserts 1 to [] & we have [1]. Then it inserts 2 to its head & so we have [2,1]. Then it inserts 3 & we have [3,2,1] & so on. So ultimately we should get y as [10,9..1]. But instead we get y as [1..10]. Why is that so?
Because it "inserts" them at list's tail (while the list is being built), not head (cf. "tail recursion modulo cons"):
[a | a <- [1..10]] ==
[a | a <- (1:[2..10])] == -- [a | a <- ([1] ++ [2..10])]
1 : [a | a <- [2..10]] -- [1] ++ [a | a <- [2..10]]
This is because
[a | a <- (xs ++ ys)] == [a | a <- xs] ++ [a | a <- ys]
and
[a | a <- ys] == ys
The way you are thinking about list comprehensions is not quite correct. When you see a comprehension
y <- [f a | a <- x]
you shouldn't think about the successive result being added to the front of an (initially empty) result list.
Instead, think of each f a being added to the front of the result of running the list comprehension on the rest of x. That is,
[f a | a <- x:xs] == f x : [f a | a <- xs]
This is a recursive approach - by assuming that the result list exists for the tail of the list, you can add the next result to the front of it.
It's instructive to look at exactly how list comprehensions desugar to monadic computations, rather than use the intuition for how they work.
[a | a <- [1..3]] == do {a <- [1..3]; return a} -- desugared comprehension
== [1..3] >>= return a -- desugared do
== concat (map return [1..3]) -- definition of >>=
== concat [[1], [2], [3]] -- defintiion of return
== [1,2,3] -- definition of concat

list comprehension never ends

This function was made for me for solving a problem in project euler, but I don't know why it doesn't end. I thought there was the "n" in the list comprehension as results, but I've changed to "x + y" and still doesn't work.
writable :: Int -> [Int]
writable n
| n `elem` primes = []
| otherwise = [x + y | x <- primes_less, y <- double_of_squares, x + y == n]
where
primes_less = takeWhile (< n) primes
double_of_squares = takeWhile (< n) $ map (\x -> 2*x*x) [1..]

haskell infinite list of incrementing pairs

Create an infinite list pairs :: [(Integer, Integer)] containing pairs of the form (m,n),
where each of m and n is a member of [0 ..]. An additional requirement is that if (m,n)
is a legit member of the list, then (elem (m,n) pairs) should return True in finite time.
An implementation of pairs that violates this requirement is considered a non- solution.
****Fresh edit Thank you for the comments, Lets see if I can make some progress****
pairs :: [(Integer, Integer)]
pairs = [(m,n) | t <- [0..], m <- [0..], n <-[0..], m+n == t]
Something like this? I just don't know where it's going to return True in finite time.
I feel the way the question is worded elem doesn't have to be part of my answer. Just if you call (elem (m,n) pairs) it should return true. Sound right?
Ignoring the helper method, the list comprehension you have will list out all pairs but the order of elements is a problem. You'll have a infinitely many pairs like (0, m) which are followed by infinitely many pairs like (1, m). Of course elem will forever iterate all the (0, m) pairs never reaching (1, m) or (2, m) etc.
I'm not sure why you have the helper method -- with it, you are only building a list of pairs like [(0,0), (1,1), (2,2), ...] because you've filtered on m = n. Was that part of the requirements?
Like #hammar suggested, start with 0 = m + n and list out the pairs (m, n). Then list pairs (m, n) where 1 = m + n. Then your list will look like [(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...].
The helper function ensures that pairs is a list of the form [ (0,0) , (1,1) , (2,2) ... ].
So elem ( m , n ) pairs can be implemented as:
elem (m , n) _ | m == n = True
| otherwise = False
This is a constant time implementation.
I first posted
Prelude> let pairs = [(m, n) | t <- [0..]
, let m = head $ take 1 $ drop t [0..]
, let n = head $ take 1 $ drop (t + 1) [0..]]
Which, I believed answered the three conditions set by the professor. But hammar pointed out that if I chose this list as an answer, that is, the list of pairs of the form (t, t+1), then I might as well choose the list
repeat [(0,0)]
Well, both of these do seem to answer the professor's question, considering there seems to be no mention of the list having to contain all combinations of [0..] and [0..].
That aside, hammer helped me see how you can list all combinations, facilitating the evaluation of elem in finite time by building the infinite list from finite lists. Here are two other finite lists - less succinct than Hammar's suggestion of the diagonals - that seem to build all combinations of [0..] and [0..]:
edges = concat [concat [[(m,n),(n,m)] | let m = t, n <- take m [0..]] ++ [(t,t)]
| t <- [0..]]
*Main> take 9 edges
[(0,0),(1,0),(0,1),(1,1),(2,0),(0,2),(2,1),(1,2),(2,2)]
which construct the edges (t, 0..t) (0..t, t), and
oddSpirals size = concat [spiral m size' | m <- n] where
size' = if size < 3 then 3 else if even size then size - 1 else size
n = map (\y -> (fst y * size' + div size' 2, snd y * size' + div size' 2))
[(x, t-x) | let size' = 5, t <- [0..], x <- [0..t]]
spiral seed size = spiral' (size - 1) "-" 1 [seed]
spiral' limit op count result
| count == limit =
let op' = if op == "-" then (-) else (+)
m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
nextOp = if op == "-" then "+" else "-"
nextOp' = if op == "-" then (+) else (-)
n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
n' = foldl (\a b -> a ++ [(nextOp' (fst $ last a) b, snd $ last a)]) n (replicate count 1)
in n'
| otherwise =
let op' = if op == "-" then (-) else (+)
m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
nextOp = if op == "-" then "+" else "-"
nextOp' = if op == "-" then (+) else (-)
n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
in spiral' limit nextOp (count + 1) n
*Main> take 9 $ oddSpirals 3
[(1,1),(0,1),(0,2),(1,2),(2,2),(2,1),(2,0),(1,0),(0,0)]
which build clockwise spirals of length 'size' squared, superimposed on hammar's diagonals algorithm.
I believe the solution to your task is:
pairs = [(x,y) | u <- [0..], x <- [0..u], y <-[0..u] , u == x+y]

Error in nested list comprehension in Haskell code

I am trying to write the following list comprehension in Haskell and it doesn't typecheck. I am new at this and can't really figure out why.
something :: Int -> [Int]
something n = [[ 2 * x + 1 | x <- xs]|xs <- [3..n],i <- [1..],j <-[1..] ,xs == i+j+2*i*j,i<=j,i>=1]
This is what I see:
Couldn't match expected type `Int' with actual type `[t0]'
In the expression: [2 * x + 1 | x <- xs]
NB: There could be a lot more wrong with this piece of code.
Here's what I am really trying to learn to do. From a list of all naturals from 3 to n(which is the Int input to the function), I want to extract just the subset of numbers which can be written as i+j+2*i*j where i, j are integers and the i<=j and i>=1. To this subset list , I want to apply the function 2*x+1 to each element x and output a final list.
Hope that makes sense.
First of all you have a nested list comprehension, so you're creating a list of lists, so the return type should be [[Int]] (list of lists of ints) and not [Int] (list of ints).
Second of all xs is a number (because you take it out of a list of numbers), but its name suggests that it's a list and when you do x <- xs you're actually treating it as if it was a list.
In response to your edit: I don't really see why you thought you needed nested list comprehensions for this. If we just remove the nesting from your code, we get something that is pretty close to working (I've also renamed xs to x because calling a number xs is just confusing - I've also removed the condition that i is at least 1 because that's already a given since you take i from the list [1..]):
[ 2 * x + 1 | x <- [3..n], i <- [1..],j <-[1..] ,x == i+j+2*i*j,i<=j]
Now this compiles, but it will loop forever. Why does it loop forever? Because you take i and j from infinite lists. This means it will start with x=3, i=1, j=1 and then try all values for j from 1 to infinity before it will try the next value of i (so in other words it will never try the next value of i).
So what we need to do is to give i and j upper bounds. An easy upper bound to pick is x (if i or j are greater than x (and neither is smaller than 1), i+j+2*i*j can't possibly be equal to x), so you get:
[ 2 * x + 1 | x <- [3..n], i <- [1..x],j <-[1..x], x == i+j+2*i*j, i<=j]
This works, but it can still be simplified a bit by somewhat: If we take j from the list [i..n] instead of [1..n], we guarantee that j is at least i and we don't need the condition i<=j anymore, so we can write:
[ 2 * x + 1 | x <- [3..n], i <- [1..x], j <-[i..x], x == i+j+2*i*j]
PS: Doing it this way (iterating over all x and then iterating over all possible values of i and j for each x) is a bit inefficient, so you might reconsider your approach. On the other hand if all you need is something that works, this is fine.
First, a function name must not be upper-case.
xs <- [3..n] means that xs is an Int, but x <- xs uses it as a list.
The rest of the comprehension looks a little bit strange, too. If you care to explain what exactly you want to do, we might be able to help a little bit more. :-)
[Edit]
You get an infinite list of your numbers by using [i+j+2*i*j| j <-[2..], i<-[1..(j-1)]], but it's not sorted. [x| x <-[3..(2*n*n)], j <-[2..n], i<-[1..(j-1)], x==i+j+2*i*j] gives a sorted list of all such numbers smaller than 2n².
Let's start with what you've got.
something n = [[ 2 * x + 1 | x <- xs]|xs <- [3..n],i <- [1..],j <-[1..] ,xs == i+j+2*i*j,i<=j,i>=1]
The basic problem here is that you don't need a nested list comprehension.
something n = [ 2 * x + 1 | x <- [3..n], i <- [1..], j <- [1..], x == i+j+2*i*j, i<=j, i>=1]
This will compile. But there is, as you suspect, a lot more wrong with this piece of code.
Let's start with the conditions. Testing for i>=1 is superfluous, given that i <- [1..].
something n = [ 2 * x + 1 | x <- [3..n], i <- [1..], j <- [1..], x == i+j+2*i*j, i<=j]
Similarly, we can get rid of the i<=j condition if we start j off at i instead of at 1.
something n = [ 2 * x + 1 | x <- [3..n], i <- [1..], j <- [i..], x == i+j+2*i*j]
It should be clear that values of j greater than (n - i) `div` (1 + 2 * i) cannot possibly result in an x ≤ n.
something n = [ 2 * x + 1 | x <- [3..n], i <- [1..], j <- [i .. (n - i) `div` (1 + 2 * i)], x == i+j+2*i*j]
Similarly, values of i of n `div` 3 or above cannot possibly result in an x ≤ n.
something n = [ 2 * x + 1 | x <- [3..n], i <- [1 .. (n `div` 3) - 1], j <- [i .. (n - i) `div` (1 + 2 * i)],
x == i+j+2*i*j]
At this point we have done enough for something to actually generate results. But there are duplicate values (e.g. when (i,j) is either (1,7) or (2,4) you get x = 22), which I assume you don't want.
We filter them out using nub from Data.List.
something n = nub [ 2 * x + 1 | x <- [3..n], i <- [1 .. (n `div` 3) - 1],
j <- [i .. (n - i) `div` (1 + 2 * i)], x == i+j+2*i*j]
There's no need to check that x satisfies a condition when we could construct x to satisfy that condition in the first place. (You will want to satisfy yourself that 3 ≤ x ≤ n still.) This is more efficient.
something n = nub [ 2 * x + 1 | i <- [1 .. (n `div` 3) - 1], j <- [1 .. (n - i) `div` (1 + 2 * i)],
let x = i+j+2*i*j]
The results are no longer coming out in ascending order, so let's make sure they do.
something n = sort $ nub [ 2 * x + 1 | i <- [1 .. (n `div` 3) - 1], j <- [1 .. (n - i) `div` (1 + 2 * i)],
let x = i+j+2*i*j]
On a style point, the doubling and adding one is a separate calculation from ensuring that x can be expressed as i+j+2*i*j, so let's split them up.
something n = sort $ map f $ nub [ x | i <- [1 .. (n `div` 3) - 1], j <- [1 .. (n - i) `div` (1 + 2 * i)],
let x = i+j+2*i*j]
where f x = 2 * x + 1
This allows us to get rid of x from the list comprehension.
something n = sort $ map f $ nub [ i+j+2*i*j | i <- [1 .. (n `div` 3) - 1],
j <- [1 .. (n - i) `div` (1 + 2 * i)]]
where f x = 2 * x + 1
Done.