Piszę funkcję, która wykonuje wyszukiwanie w sekwencji dowolnych symboli. Chciałbym uczynić go generycznym na tyle, aby działał na listach, Foldable
s oraz na ByteString
s i Text
s. Uogólnienie go na Foldable
jest proste. Ale jak dołączyć ByteString
s i Text
s? Pewnie mógłbym zamienić ByteString
na listę, a następnie zadzwonić do mojej funkcji, ale straciłbym wszystkie zalety ByteString
s.Tworzenie pojedynczej funkcji działa na listach, ByteStringach i tekstach (i być może na innych podobnych reprezentacjach)
mieć konkretny przykład załóżmy, że chcemy, aby funkcja 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ż ani ByteString
ani tekst można Foldable
(Przechowuje tylko Word8
s/Char
s, a nie arbitralne elementy), Utknąłem z tworzeniem więcej funkcji, które wyglądają dokładniejak jeden przed, tylko z różnymi podpisami typu:
histogramBS :: B.ByteString -> Histogram Word8
histogramBS = B.foldl (flip histogramStep) empty
histogramText :: T.Text -> Histogram Char
histogramText = T.foldl (flip histogramStep) empty
ten jest czymś, czego się nie spodziewa w tak funkcjonalnym języku jak Haskell.
Jak zrobić to ogólne, aby napisać histogram
raz na zawsze?
Zawsze zadajesz ciekawe pytania, ponieważ głęboko myślisz o tym, co robisz i zawsze chcesz zrozumieć więcej. +1 – AndrewC