Tworzenie pojedynczej funkcji na listach, ByteStrings i Texts (i być może innych podobnych reprezentacjach)

Piszę funkcję, która przeszukuje niektóre sekwencje dowolnych symboli. Chciałbym, aby była wystarczająco ogólna, aby działała na listach,Foldables równie dobrzeByteStrings iTexts. Uogólniając toFoldable jest proste. Ale jak zawrzećByteStrings iTexts? Jasne, że mogę się nawrócićByteString do listy, a następnie zadzwoń do mojej funkcji, ale stracę wszystkie zaletyByteStrings.

Aby mieć konkretny przykład, powiedzmy, że chcemy utworzyć funkcję histogramu:

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

Ale ponieważ żaden z nichByteString ani Tekst nie może byćFoldable (przechowuje tylkoWord8s /Chars, a nie dowolne elementy), utknąłem z tworzeniem większej liczby funkcji, które wyglądajądokładnie jak poprzednio, tylko z różnymi podpisami typów:

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

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

To jest coś, czego nie można oczekiwać w języku funkcjonalnym, takim jak Haskell.

Jak sprawić, aby było ogólne, pisaćhistogram raz i na zawsze?

questionAnswers(4)

yourAnswerToTheQuestion