Fazendo uma única função funcionar em listas, ByteStrings e Textos (e talvez outras representações similares)

Eu estou escrevendo uma função que faz alguma pesquisa em uma seqüência de símbolos arbitrários. Eu gostaria de torná-lo genérico o suficiente para que ele funcione em listas,Foldables bem emByteStringareiaTexts. Generalizando paraFoldable é simples. Mas como incluirByteStringareiaTexts? Claro que eu poderia converterByteString em uma lista e depois chamar minha função, mas eu perderia todas as vantagensByteStrings.

Para ter um exemplo concreto, digamos que queremos fazer uma função histograma:

import Control.Monad.State
import qualified Data.Foldable as F
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Word
import qualified Data.ByteString as B
import qualified Data.Text as T

type Histogram a = Map a Int

empty :: (Ord a) => Histogram a
empty = Map.empty

histogramStep :: (Ord a) => a -> Histogram a -> Histogram a
histogramStep k = Map.insertWith (+) k 1

histogram :: (Ord a, F.Foldable t) => t a -> Histogram a
histogram = F.foldl (flip histogramStep) empty

Mas já que nenhum dos doisByteString nem o texto pode serFoldable (armazena apenasWord8s /Chars, não elementos arbitrários), eu estou preso com a criação de mais funções que parecemexatamente como o anterior, apenas com um tipo diferente de assinaturas:

histogramBS :: B.ByteString -> Histogram Word8
histogramBS = B.foldl (flip histogramStep) empty

histogramText :: T.Text -> Histogram Char
histogramText = T.foldl (flip histogramStep) empty

Isso é algo que não se espera em uma linguagem funcional como o Haskell.

Como tornar genérico, escreverhistogram de uma vez por todas?

questionAnswers(4)

yourAnswerToTheQuestion