将元素列表折叠成一组元素

时间:2018-10-13 11:26:26

标签: haskell set

我想将一个列表折叠成一个集合,但是我的实现似乎要求该列表已经是一个集合。 Element有一个Ord实例。导入正确。

listToSet :: [Element] -> Set Element
listToSet d = foldl' insert empty d

d在这里应该已经是一个集合,所以这当然会导致类型错误,我可以使用foldl'从列表中创建一个集合吗?我是否首先需要将Element的列表“投射”到长度为Element的每个的一组列表中?

错误:

Assignment3.hs:201:39: error:
    * Couldn't match type `Element' with `Set Element'
      Expected type: [Set Element]
        Actual type: [Element]
    * In the third argument of foldl', namely `d'
      In the expression: foldl' insert empty d
      In an equation for `listToSet':
          listToSet d = foldl' insert empty d
    |
201 | listToSet d = foldl' insert empty d
    |     

2 个答案:

答案 0 :(得分:4)

您不小心引用了Data.Set.foldl'而不是Data.List.foldl'。您需要同时导入两个模块,然后消除歧义:

listToSet :: [Int] -> Set Int
listToSet d = Data.List.foldl' (flip Data.Set.insert) empty d

更好的是,使用合格的导入:

import qualified Data.Set as S
import Data.List

listToSet :: [Int] -> S.Set Int
listToSet d = foldl' (flip S.insert) S.empty d

甚至更好的是,直接使用S.fromList:它已经存在于库中,因此没有必要重新发明轮子(除非作为练习)。

答案 1 :(得分:1)

foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b具有类型为b -> a -> b的函数作为第一个参数,因此您应首先提供Set进行更新,然后提供要插入的元素,然后生成一个新的{{ 1}}。

然而,insert :: Ord a => a -> Set a -> Set a以相反的方式获取参数:首先输入要插入的元素,然后以Set进行更新。

因此,您可以使用flip :: (a -> b -> c) -> b -> a -> c来“翻转参数”,并构造一个具有Set可以处理的顺序的参数的函数,因此我们可以定义如下函数:

foldl'

请注意,您此处要定义的内容已经存在:import Data.Set(empty, insert) import Data.List(foldl') listToSet :: (Foldable f, Ord e) => f e -> Set e listToSet = foldl' (flip insert) empty模块具有fromList :: Ord a => [a] -> Set a函数,可从Data.Set中生成Set a

相关问题