snoyberg/mono-traversable's README notes
[MonoFoldable is the same] as Foldable, but also operates over monomorphic containers.
Please give an example where Foldable does not operate over monomorphic containers.
snoyberg/mono-traversable's README notes
[MonoFoldable is the same] as Foldable, but also operates over monomorphic containers.
Please give an example where Foldable does not operate over monomorphic containers.
Text is intuitively a container, however it is not polymorphic. Hence
Prelude> Data.Foldable.foldr ((:) . fromEnum) [] (Data.Text.pack "blub")
<interactive>:8:28: error:
• Couldn't match expected type ‘[a0]’
with actual type ‘Data.Text.Internal.Text’
• In the third argument of ‘foldr’, namely
‘(Data.Text.pack "blub")’
In the expression:
foldr ((:) . fromEnum) [] (Data.Text.pack "blub")
In an equation for ‘it’:
it = foldr ((:) . fromEnum) [] (Data.Text.pack "blub")
OTOH,
Prelude> Data.MonoTraversable.ofoldr ((:) . fromEnum) [] (Data.Text.pack "blub")
[98,108,117,98]
A Foldable has kind * -> *. Lists, trees, basically anything that can take another type for their element type has that kind. Any instance of Foldable must be a type constructor , not a type , since the class is defined as
class Foldable (t :: * -> *) where
foldMap :: Monoid m => (a -> m) -> t a -> m
-- ^ ^
However, Text, ByteString and other types are clearly a collection of some underlying element type, yet their kind is *. They aren't type constructors, they are already types. They don't fit foldMap's type:
listLength :: Text -> Int
listLength = getSum . foldMap (const (Sum 1))
textLength :: Text -> Int
textLength = foldMap magic -- will never compile, for no magic
I think what's meant here is, that usually when talking about Foldable we mean the higher-kinded polymorphic version. I.e. List is a Foldable for all a. So Foldable works on types * -> * (also called type constructors).
The MonoFoldable type class works on actual types instead. So for example we could write an instance of MonoFoldable for something like Text.
ByteString and Text, which can only contain Word8 and Char respectively. Also unboxed arrays have a restriction on their data type so can't be directly made instances of Foldable.
Note however you can trivially make a Monofoldable into a Foldable just by wrapping it appropriately. My package make-monofoldable-foldable does that for you, so for example if you need to pass a ByteString to a function that expects a Foldable you can just wrap it with WrappedMonoFoldable and then pass it in.