Home > Net >  How to get [Int] instead of [[Int]] Haskell
How to get [Int] instead of [[Int]] Haskell

Time:05-27

I am a newbie to Haskell functional programming. I've studied lambda functions, lists,types, record syntax, and functors from several sources like Learn You a Haskell for Great Good a book called Get Programming With Haskell. I get some idea of how functions works and essentials of functional programming. At this point, I stuck at the point where I need to use list of records inside lamda functions which is a parameter of a map function.

Here I share runable code.

I have a record of Person

data Person = Person
 {name :: Name
 ,lastname :: LastName
 ,personId :: Int
 ,sex :: Int
 ,parentList ::  [Int]
 ,childList :: [Int]
 ,siblingList :: [Int]
 }
 deriving (Show,Typeable,Data,Eq)

1- I have a getParentListPerson :: Person-> [Person] -> [Person] function that returns parents of a given Person using [Person] list. (I hold every person in everybody :: [Person] )

getParentListPerson :: Person-> [Person] -> [Person]
getParentListPerson p ps = filter((\px -> elem (personId p) (childList px))) ps

2- And isCousen function that returns true if the first parameter and the second parameter is cousens.(where first person's one of parents should be in the siblingList of second person's one of parents)

isCousen :: Person -> Person -> Bool
isCousen p1 p2 =any f (parentList p1)
        where f= (\x -> elem x $ map func2 $ func3 p2 everybody):([Int]->Bool)
              func2 = (\y -> (siblingList y))::(Person->[Int])
              func3 = (\z k-> getParentListPerson z k)::(Person->[Person]->[Person])

Here what I am trying to do is to create a lambda function f that takes parentList ([Int]) and finds any matching person.

  1. f :: [Int]->Bool
  2. funcs2 :: Person -> [Int].
  3. func3 :: Person -> [Person ] -> [Person].

When I run this I get this error: (As far as I understand although I want to give a Person to func2 using map in where clause I cannot achive. I know that map takes a function and a list.So I assume func3 cannot return [Person].So the problem should be in the getParentListPerson function)

app\Main.hs:89:24: error:
    * Couldn't match type `Int' with `[Int]'
      Expected type: [[Int]]
        Actual type: [Int]
    * In the second argument of `any', namely `(parentList p1)'
      In the expression: any f (parentList p1)
      In an equation for `isCousen':
          isCousen p1 p2
            = any f (parentList p1)
            where
                f = (\ x -> elem x <$> concatMap func2 <$> func3 p2 everybody) ::
                      ([Int] -> Bool)
                func2 = (\ y -> (siblingList y)) :: (Person -> [Int])
                func3
                  = (\ z k -> getParentListPerson z k) ::
                      (Person -> [Person] -> [Person])
   |
89 | isCousen p1 p2 =any f (parentList p1)
   |                        ^^^^^^^^^^^^^

It says that I am giving [Int] where the expected parameter should be [[Int]]. I am a bit lost. Any help would be appreciated. I suspect that I may use map function and lambda functions incorrectly but I did what I can. They seem correct from my knowledge

CodePudding user response:

The problem is that func2 returns a list which means that map func2 returns a list of lists. What you want to probably do is to concatenate these together. Thus change:

elem x $ map func2 $ func3 p2 everybody

into:

elem x $ concat $ map func2 $ func3 p2 everybody

There's also a combination of concat and map namely concatMap so you can simplify it into:

elem x $ concatMap func2 $ func3 p2 everybody

It seems that you have switched to this according to comment by chi which is reflected in the error message though you have still left the original code unchanged. The problem with this appears to be that you have also replaced every $ with <$> which is not correct because <$> does the same thing as map. If you want to use <$> you can replace map with it like so:

elem x $ concat $ func2 <$> func3 p2 everybody

Then I can also note how some of your functions could be simplified somewhat (even though you didn't ask about that). You don't need to use all or any of these simplifications but you might at least consider them.

In the following functions you use lambda.

func2 = (\y -> (siblingList y))
func3 = (\z k-> getParentListPerson z k)

Since the lambda is the entire expression you can just use normal function syntax for these instead of lambda like so:

func2 y = siblingList y
func3 z k = getParentListPerson z k

But now you can also notice that these do nothing but apply arguments to a function so they're equivalent to:

func2 = siblingList
func3 = getParentListPerson

But since now we can see that func2 and func3 are basically just function aliases we can just remove them and substitute siblingList and getParentListPerson for them in the definition of f like so:

f = (\x -> elem x $ concatMap siblingList $ getParentListPerson p2 everybody)

Here you can also remove the lambda:

f x = elem x $ concatMap siblingList $ getParentListPerson p2 everybody

You could also simplify getParentListPerson a little bit in somewhat similar manner. Alternatively, you could also instead use parentList though you'd then need to convert each Int into Person.

Btw, the word "Cousin" is misspelled in the function name isCousen.

  • Related