0
votes

I have the following code in haskell and I get

  1. Couldn't match type [Int] with `Bool'
  2. Couldn't match type [[a0]] -> [a0]' with[Int]' Expected type: [Int] -> [Int] Actual type: [Int] -> [[a0]] -> [a0]

Code:

findlist:: [[Int]] -> [Int] 
findlist (l1, l2, l3, l4, l5) = do      1)
    let n = length l1
    e1 <- [1..n]
    e2 <- [1..n]
    e3 <- [1..n]
    e4 <- [1..n]
    e5 <- [1..n]
    let list1 = pick_list $ myperms e1 l1   --here
        list2 = pick_list $ myperms e2 l2   --here
        list3 = pick_list $ myperms e3 l3   --here
        list4 = pick_list $ myperms e4 l4   --here
        list5 = pick_list $ myperms e5 l5   --here
    guard $ all (== list1) $ [list2, list3, list4, list5]
    guard $ e1 `notElem` [e2, e3, e4, e5]
    guard $ e2 `notElem` [e3, e4, e5]
    guard $ e3 `notElem` [e4, e5]
    guard $ e4 `notElem` [e5]
    return concat list1                    2)

Type signatures:

pick_list:: [[Int]] -> [Int]
myperms:: Int -> [Int] -> [[Int]] 

What's wrong with it and how can I realize when I'm gonna get such errors? Thanks in advance.

1
I don't get the errors you have. If I put in myperms :: Int -> [Int] -> [[Int]]; myperms = undefined and pick_list :: [[Int]] -> [Int]; pick_list = undefined. Additionally, I doubt you tried to compile this exact code because findlist takes a 5-tuple, not a list, but you clearly have given it a type signature that says it takes a list. That's the only compile error I get with this code.bheklilr
It's OK now but it's slow. I've thought about limiting the range of the e1, e2 and so on but I need a function that deletes a given sublist of a given list.Billy Grande
In that case it go like e2<-(delete e1 [1..n]), e3<-(mydelete [e1,e2] [1..n]) and so on. So I could use only the "all" guard. Btw, pick_list was stupid. All I needed was list1<- (myperms e1 l1) and so on..Billy Grande

1 Answers

1
votes

Your where clause needs to be indented underneath findlist. However, this code has more problems than just that.


The first big problem I see is that you're getting particular elements of list, but you haven't ensured that it has at least 5 elements. Maybe you should be passing in a tuple instead?

Second, you reference elem1, elem2, etc in the where clause, but they aren't in scope outside of the list comprehension, they can't be used outside of the square brackets.

Third is that your comprehension will return copies of list1, one for each successful match in your huge list comprehension condition. Even if it could compile, I don't think this code would do what you want it to.


You could instead write this in a monadic form. I've taken the liberty of simplifying your checks using Control.Monad.guard as well and getting rid of elements:

findlist (l1, l2, l3, l4, l5) = do
    let n = length l1
    e1 <- [1..n]
    e2 <- [1..n]
    e3 <- [1..n]
    e4 <- [1..n]
    e5 <- [1..n]
    let list1 = pick_list $ myperms e1 l1
        list2 = pick_list $ myperms e2 l2
        list3 = pick_list $ myperms e3 l3
        list4 = pick_list $ myperms e4 l4
        list5 = pick_list $ myperms e5 l5
    guard $ all (== list1) [list2, list3, list4, list5]
    guard $ e1 `notElem` [e2, e3, e4, e5]
    guard $ e2 `notElem` [e3, e4, e5]
    guard $ e3 `notElem` [e4, e5]
    guard $ e4 `notElem` [e5]
    return list1

This code is certainly a lot easier to read, and it will have equivalent performance (which will be slow for large n)