对我来说,整数集似乎是可折叠的数据结构。
为什么Data.IntSet
不是Foldable
的实例?
我的实际意图是在find
上使用IntSet
。
如何实现Data.IntSet
的查找?
最佳答案
IntSet
不能是Foldable
包中的base
,因为它没有种类* -> *
。
ghci> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
ghci> :k Foldable
Foldable :: (* -> *) -> Constraint
ghci> import Data.IntSet (IntSet)
ghci> :k IntSet
IntSet :: *
简而言之,要成为
Foldable
中base
的实例,您的数据类型应通过某种类型变量进行参数设置。如果要在IntSet
上使用某些操作,则应使用Data.IntSet
模块中已实现所有专用版本的某些功能。但我想补充一下,存在
Foldable
的版本,该版本的IntSet
可以实例化(和we actually did this in our library,这是在MonoFoldable
之前完成的)。您只需要正确实现抽象:{-# LANGUAGE TypeFamilies #-}
type family Element t
type instance Element (f a) = a
type instance Element Text = Char
type instance Element IntSet = Int
class ProperFoldable t where
foldr :: (Element t -> b -> b) -> b -> t -> b
UPDATE(通过请求添加
find
):由于
find :: (a -> Bool) -> IntSet -> Maybe a
类型变量,您无法实现a
。您能否回答“什么是a
?”问题? IntSet
不是多态容器。它仅包含Int
。因此,您可以实现的最大值是find :: (Int -> Bool) -> IntSet -> Maybe Int
。仅通过将IntSet
转换为这样的列表,就没有有效的方法来实现此功能:import Data.Foldable (find)
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
intSetFind :: (Int -> Bool) -> IntSet -> Maybe Int
intSetFind predicate = find predicate . IS.elems