For me, an integer set seems to be a foldable data structure.
Why is Data.IntSet
not an instance of Foldable
?
My actual intention is to use find
on an IntSet
.
How can I implement find for Data.IntSet
?
For me, an integer set seems to be a foldable data structure.
Why is Data.IntSet
not an instance of Foldable
?
My actual intention is to use find
on an IntSet
.
How can I implement find for Data.IntSet
?
IntSet
can't be Foldable
from base
package because it doesn't have kind * -> *
.
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 :: *
In simple words, to be instance of Foldable
from base
you data type should be parametrized by some type variable. If you want to use some operation on IntSet
you should use some function from Data.IntSet
module where all specialized versions implemented.
But I want to add that there exist version of Foldable
which IntSet
can instantiate (and we actually did this in our library and this was done earlier with MonoFoldable
). You just need to implement your abstractions properly:
{-# 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 (adding find
by request):
You can't implement find :: (a -> Bool) -> IntSet -> Maybe a
because of a
type variable. Can you answer question «What is a
?»? IntSet
is not polymorphic container. It contains only Int
s. So maximum you can implement is find :: (Int -> Bool) -> IntSet -> Maybe Int
. And there's no efficient way to implement this function, only by converting IntSet
to list like this:
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
Element
should probably be an associated type family. :) –
Medeah find :: (a -> Bool) -> IntSet -> Maybe a
? –
Lewendal ProperFoldable
without also the type family instance. Otherwise, you are much more likely to end up with stuck type family applications. –
Medeah find
implementation. –
Marashio type Element t :: a; type Element (f a) = a
. Personally, I prefer to make the element type the first class parameter as well, with an equality constraint. –
Crinkle IntSet
foldable with MonoFoldable
. What I don't understand is why you can't have a function that efficiently searches for the first Int
in an IntSet
that satisfies some predicate. In a procedural language, It would make no difference if the container was polymorphic or not. Sorry if this is a stupid question, I'm new to haskell. –
Lewendal Int -> Bool
and you don't know anything about it inside find
function. All you have is list of sorted Int
s. For example, I don't know how to implement find even
efficiently (faster than O(n)) for sorted list of integers. –
Marashio find
is first converting the set into a list so the complexity should be 2n instead of n worst-case If I'm not mistaken. –
Lewendal find
function happen. But Haskell is lazy language. You can think of IS.elems
as of lazy iterator which produces values of IntSet
on demand and find
function calling this iterator while necessary. So in practice there would be no 2n. Always lower. –
Marashio © 2022 - 2024 — McMap. All rights reserved.
Data.IntSet
may not beFoldable
, but it does providefoldl
andfoldr
implementations. There's also amember
function which performs your typicalfind
operation. If you wanted to implement your ownfind
function, there areLookupLE
,LookupGT
etc functions which would let you perform a binary search. Workaround though. – Otalgiaclass Foldable
applies to* -> *
kinds, andIntSet
is a*
kind. – DevilfishIntSet
is an instance ofMonoFoldable
. – Lop