Пиша функция, която извършва известно търсене в поредица от произволни символи. Бих искал да го направя достатъчно общ, така че да работи на списъци, Foldable
s, както и на ByteString
s и Text
s. Обобщаването му до Foldable
е просто. Но как да включите ByteString
s и Text
s? Разбира се, че мога да конвертирам ByteString
в списък и след това да извикам моята функция, но бих загубил всички предимства ByteString
s.
За да имаме конкретен пример, нека кажем, че искаме да направим функция хистограма:
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
Но тъй като нито ByteString
, нито Text могат да бъдат Foldable
(съхранява само Word8
s/Char
s, а не произволни елементи), аз съм прикован към създаването на повече функции, които изглеждат точно като предишната, само с различен тип подписи:
histogramBS :: B.ByteString -> Histogram Word8
histogramBS = B.foldl (flip histogramStep) empty
histogramText :: T.Text -> Histogram Char
histogramText = T.foldl (flip histogramStep) empty
Това е нещо, което човек не очаква във функционален език като Haskell.
Как да го направя общ, да напиша histogram
веднъж завинаги?