我想将一个列表折叠成一个集合,但是我的实现似乎要求该列表已经是一个集合。 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
|
答案 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
。