Sto scrivendo una funzione che esegue una ricerca in una sequenza di simboli arbitrari. Mi piacerebbe renderlo abbastanza generico in modo che funzioni sugli elenchi, Foldable
s su ByteString
s e Text
s. Generalizzarlo a Foldable
è semplice. Ma come includere ByteString
se Text
s? Certo, potrei convertire ByteString
in una lista e quindi chiamare la mia funzione, ma perderei tutti i vantaggi ByteString
s.Esecuzione di una singola funzione su elenchi, ByteStrings e testi (e forse altre rappresentazioni simili)
Per avere un esempio concreto diciamo che vogliamo fare una funzione istogramma:
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
Ma poiché né ByteString
né testo può essere Foldable
(esso memorizza solo Word8
s/Char
s, non elementi arbitrari), sono bloccato con la creazione di più funzioni che sembrano esattamente come il precedente, solo con un diverso tipo di firme:
histogramBS :: B.ByteString -> Histogram Word8
histogramBS = B.foldl (flip histogramStep) empty
histogramText :: T.Text -> Histogram Char
histogramText = T.foldl (flip histogramStep) empty
Questo è qualcosa che non ci si aspetta in un linguaggio funzionale come Haskell.
Come renderlo generico, per scrivere histogram
una volta per tutte?
Voi chiedete sempre domande interessanti perché si pensa profondamente su quello che stai facendo e sempre voglia di capire di più. +1 – AndrewC