Kevin Meredith
Kevin Meredith

Reputation: 41909

Understanding Monomorphic Containers w/ Foldable

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.

Upvotes: 4

Views: 278

Answers (4)

Clinton
Clinton

Reputation: 23135

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.

Upvotes: 1

Zeta
Zeta

Reputation: 105886

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

Upvotes: 4

Luka Jacobowitz
Luka Jacobowitz

Reputation: 23502

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.

Upvotes: 1

leftaroundabout
leftaroundabout

Reputation: 120711

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]

Upvotes: 7

Related Questions