任意のシンボルのシーケンスで検索を行う関数を作成しています。Foldable
リストやs だけでなくByteString
s やs でも機能するように、十分に一般的なものにしたいと思いますText
。それを一般化するの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 も Text もできないため(任意の要素ではなくs/ sFoldable
のみを格納する)、型シグネチャが異なるだけで、以前のものとまったく同じように見える関数をさらに作成することに行き詰まっています。Word8
Char
histogramBS :: B.ByteString -> Histogram Word8
histogramBS = B.foldl (flip histogramStep) empty
histogramText :: T.Text -> Histogram Char
histogramText = T.foldl (flip histogramStep) empty
これは、Haskell のような関数型言語では予期しないことです。
ジェネリックにする方法、histogram
一度だけ書く方法は?