如何获得 [Int] 而不是 [[Int]] Haskell

How to get [Int] instead of [[Int]] Haskell

我是 Haskell 函数式编程的新手。我从 Learn You a Haskell for Great Good 一本名为 Get Programming With Haskell 的书等多个来源研究了 lambda 函数、列表、类型、记录语法和仿函数。我对函数的工作原理和函数式编程的要点有了一些了解。在这一点上,我停留在需要在 lamda 函数中使用记录列表的位置,它是 map 函数的参数。

Here 我分享 运行 有效代码。

我有记录个人

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

1- 我有一个 getParentListPerson :: Person-> [Person] -> [Person] 函数 returns parents 使用 [Person] 列表的给定 Person。 (我把每个人都放在 everybody :: [Person]

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

2-并且是Cousen函数如果第一个参数和第二个参数是Cousens则return为真。(其中第一人称 parents 应该在第二人称 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])

这里我想做的是创建一个 lambda 函数 f 接受 parentList ([Int]) 并找到任何匹配的人。

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

当我 运行 这个时,我得到这个错误: (据我所知,虽然我想在 where 子句中使用 map 给 func2 一个 Person 我无法实现。我知道 map 有一个函数和一个 list.So I assume func3 cannot return [Person]. 所以问题应该在 getParentListPerson 函数中)

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)
   |                        ^^^^^^^^^^^^^

它说我正在给 [Int],而预期的参数应该是 [[Int]]。我有点迷路了。任何帮助,将不胜感激。 我怀疑我可能错误地使用了 map 函数和 lambda 函数,但是 我已经尽力了。 他们据我所知似乎是正确的

问题是func2returns一个列表,也就是说map func2returns一个列表的列表。您可能想要做的是将它们连接在一起。因此改变:

elem x $ map func2 $ func3 p2 everybody

进入:

elem x $ concat $ map func2 $ func3 p2 everybody

还有concatmap的组合,即concatMap所以你可以简化为:

elem x $ concatMap func2 $ func3 p2 everybody

看来你已经根据chi的评论切换到了这个,这反映在错误消息中,尽管你仍然保持原始代码不变。这个问题似乎是您还用 <$> 替换了每个 $,这是不正确的,因为 <$>map 做同样的事情。如果你想使用 <$> 你可以像这样替换 map:

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

然后我还可以注意到您的一些功能可以如何简化(即使您没有问过)。您不需要使用所有或任何这些简化,但您至少可以考虑它们。

在以下函数中您使用了 lambda。

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

由于 lambda 是整个表达式,因此您可以使用普通函数语法代替 lambda,如下所示:

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

但现在您还可以注意到,这些除了将参数应用于函数外什么都不做,因此它们等效于:

func2 = siblingList
func3 = getParentListPerson

但是现在我们可以看到 func2func3 基本上只是函数别名,我们可以删除它们并用 siblingListgetParentListPerson 替换它们f 的定义如下:

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

这里你也可以去掉lambda:

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

您也可以采用类似的方式稍微简化 getParentListPerson。或者,您也可以改用 parentList,尽管您随后需要将每个 Int 转换为 Person.

顺便说一句,函数名称中的单词“Cousin”拼写错误 isCousen