Making ByteString and Text instances of Foldable... almost

Posted on August 14, 2015 by Aaron Rotenberg
Post tagged: Haskell

I just noticed you can do this:

{-# LANGUAGE GADTs, RankNTypes #-}

module Data.Foldable.Mono((*$*)) where

import Data.MonoTraversable(Element, MonoFoldable(..))
    -- ^ from the mono-traversable package

(*$*) :: MonoFoldable mono =>
    (forall t. Foldable t => t (Element mono) -> a) -> mono -> a
f *$* o = f (Foldabilized o)

data Foldabilized a where
    Foldabilized :: MonoFoldable mono =>
        mono -> Foldabilized (Element mono)
instance Foldable Foldabilized where
    foldr f z (Foldabilized o) = ofoldr f z o
    -- (Similar implementations for the other methods can be included
    -- here for efficiency.)

And then use it like this:

import Data.Foldable.Mono
import qualified Data.Text.Lazy as T

testText = T.pack "foo quux bar"
example1 = maximum *$* testText
    -- ^ equals 'x'
example2 = mapM_ print *$* testText
    -- ^ prints "'f'\n'o'\n'o'\n..."

Notice that those are the polymorphic Foldable functions maximum and mapM_, not Text-specific functions. I don’t know if this has any real-world applications, but it’s kind of neat…

Update: As pointed out by lfairy on Reddit, the FMList type works kind of like this.