我正在编写一个函数,该函数在一系列任意符号中进行一些搜索。我想让它足够通用,以便它适用于列表、Foldable
s 以及ByteString
s 和Text
s。将其概括为Foldable
很简单。但是如何包含ByteString
s 和Text
s 呢?当然我可以转换ByteString
成一个列表,然后调用我的函数,但我会失去所有的优势ByteString
。
举一个具体的例子,假设我们要创建一个直方图函数:
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
一劳永逸地编写?